 So let's start again, I'm Krzysztof Kosowski. I introduced myself already. So the presentation of the device tree bindings in the Linux kernel. I will shortly talk about the bindings. The expectation is that you know a bit about the device tree sources and the bindings. Then the core would be about the new format of the Linux kernel bindings, so the DT schema. The core presentation is dos and don't, so kind of tricks, which will reduce my review time. I mean, my efforts, so this is purely selfish presentation. I really hope that I will review less and faster of the submissions of people who wants to have their bindings in the kernel. The talk finishes with reusable patterns, references, which I will not be here describing, but I leave them in the presentation. Feel free to grab the PDF from theskete.org and use it in your work if you ever need some of these references. Okay, so device tree bindings and device tree sources are used in many projects. This talk is focusing on the Linux kernel implementation. So there are some differences. This is from my point of view. I build this mostly on the reviews I received and also from the reviews, which I saw on mailing list. And this talk is kind of short, even now shorter because of the technical problems, to which I apologize. Therefore, if you send some patches, you might have a bit different reviews than apologize for, I mean, the review on the mailing list supersets is more important than what I say here. Okay, so the bindings in the device tree. Device tree sources, so DTS, is the way how we describe the hardware for the Linux kernel or for the other, several other projects. And the bindings are the ways, is the rule how DTS should be constructed. It also describes some kind of, let's say the interface, because it's used for several different projects. So it's not only Linux specific. It's not implementation specific. For the older time, we wrote the bindings in text format without any structured way. And the new way of describing the bindings is the DT schema, which is using the YAML as a language itself. It has several benefits, this new format. One of the questions he was, because it allows us to validate the bindings and then against the core schema, metal schema. And it allows us to validate the device tree sources against the bindings. Therefore, to find whether the bindings are correct, of course, assuming that the bindings are correct. All the bindings would come in DT schema. You are still free to do some minor changes, like adding compatibles. However, adding in properties usually is not accepted. So you have to first make the work to convert the bindings from the text to the DT schema. This is the example. So on the left side, there is a, on the left side, there is some device tree source, there's a SPI bus, the SPI bus has one ADC node. It has a compatible unit address, REC, and so the address on the bus and has a regulator supply. On the right side, there is a corresponding DT schema bindings. I removed some boilerplate code here, it's not important. We start with the title description, which described the hardware. So this is some analog digital ADC, something with temperature sensor. We have a list of properties. We expect three properties, the compatible, which should have some specific value, like that one. We expect one unit address on the bus and we expect the supply, which is a regulator, which is optional. Why it's optional? Because it's not mentioned in a list of required properties. Required is only compatible in the REC. Entire set finishes with additional properties false, which has a meaning that no other properties can appear here. I will also describe the meaning behind these additional properties later in the presentation. What are the generic rules for the bindings? We already have a document, so I will here briefly describe, say what we already have. Hopefully, if you ever submit a patch, then please read the document fully, don't rely only on my presentation. So the same as device resources, the bindings should focus on the hardware. DTS describes the hardware, the bindings describe DTS, therefore also it's a hardware, not a implementation, especially that the bindings might be used in different projects. The linux kind of bindings are used in U-boot, are sometimes used in openBSD, freeBSD, many, many, many places. For the same reason also we prefer not to use linux-specific sub-system naming in the bindings. There are a few, let's say, not hardware related, like Deathwreck or Xcon, there are more linux-specific, so avoid them. We want the bindings to be dual-licensed, so GPL2 and BSD, for the same purpose of re-user in other projects. We want the filename to be based on the compatible, so usually the file should be named like this vendor with a device or vendor with a sort IP. Pretty often your driver comes with a header, which is also part of the bindings. Therefore, you expect this also to be dual-licensed, we like it to be also with specific filename. The bindings should not be mixed with the driver code, we expect it to be as a separate patch, preferably at the beginning of the patch set, so the driver code can be in the patch set, but not in one patch, not in one comment. More about the compatible, so this is actually one of quite important properties of the device resource. Compatible, like many things in the bindings should be specific. What does it mean that specific? First of all, we don't want any wildcars, or family names are usually also thrown upon, so the family name might require that you have a specific, other compatible in front of it. The bus suffixes for the compatibles also don't make much sense, because the bus, what the div, it's kind of obvious from the note which is enclosing the device on what it is the bus is. Linux has two specific compatibles, Syscon and SimpleMFD, I'm not sure they are used in other projects. They have a meaning in the Linux, and they are not specific enough, therefore they require a specific add-on. Usually they have to be prepended with a device-specific compatible, like in here the Qualcomm for this. SimpleMFD is very another special compatible, which has its own meaning that you can instantiate devices, children for which they don't depend on any resource that you have. It's for really simple devices, so for example if you have some clocks or power domains, then it's not for the SimpleMFD. It's only for the cases when the devices don't rely on anything of the parent. Other rules, so we focus on the hardware, I actually mentioned it before, but not exactly on the programming language of the device. So the typical example is if you have a voltage regulator and it has some minimum voltage, then the property should be expressed in the logical units, which are microvolts, not in some enumerated values which map to the voltages. Why? Because it's really much easier to read these microvolts, and it's much more partable. For example, if you want to support another type of device, let's say from the same family, which has a bit different mapping of this one, two, three, to some other voltages, so voltages are much more portable. The DT schema, so we have another dog explaining how to use it, so just I refer to it if you really want to try it, but actually it's very straightforward, so the DT schema is written in Yaml, which is pretty nice in the going language. You start it with just you have to install it with the Python package, and then one command, make DT binding check, can test your bindings against the meta schema. You can limit which bindings should be tested. You can test all your DTBS against one binding file or several bindings files, even all of them, so this is the target DTBS check. There's also a way to test one DTB against one bindings or another combination like that. Do and don't, and this is, I hope, the most useful part of this presentation, at least for me, because this will offload my review time, so this is the selfish part. The properties in the bindings, so pretty often you need some property, and pretty often you can find the standard property for it, please use it, don't invent the wheel. Where to find them? Maybe you can find them in the device tree schema repository itself, or, for example, for the GPIO, typical consumer property, like reset GPIOs, enable GPIOs, we also have the bindings, which express them, or just look at the other common parts in other bindings everywhere around. You will still need custom properties from time to time, and custom property has its own requirements, so usually you need a vendor prefix for it, so this foo behind the comma, you need a type, I will also speak about the type in a second, type is expressed with a reference, and you need a description, so this is the total example, how it would look like, so there is a Qualcomm prefix, there is a type, this is assigned integer at 32, and there's a description explaining what is this, this is in the case of number of samples. I said that you don't need types for certain cases, so the type, which is this ref, you can skip it if you have a standard, you need suffix, so the suffix means in the property name, like this microvolt, there's a list of them, here is the link, if you have two checks, or where such properties are already described by the core schema, or any other core schema. These are the examples, so the first one is entry, late in c us, us is for microsecond, therefore it's standard to need prefix, no need for type. To others is like a supply, which is also regulator, it is a pattern coming from the core schema, again no need for the reference for the type, the third one is interrupt, as well defined by the core schema. It even lacks description, and I will also mention later why it's lacks description, this interrupts part. So we are going to the arrays, like this interrupts, this is like quite common property, when you have clocks, reg, power domains, interrupts, DMAs, IOIOMs. The main requirements for such properties are they are strictly ordered. So we have kind of a helper for them, which is like with the names, so clock names, interrupt names, DMA names. Therefore the Linux implementation pretty often grabs such resource by the name. However, this is just a helper, and it does not remove the obligation that the array is strictly ordered. If you use this kind of helper, then make it specific and then don't add there any obvious suffixes, like if it's interrupt, it's just tx interrupt, not tx IRQ, no point to add IRQ. And both of them, so the clock names and the clocks, interrupts, interrupt names have to be strictly ordered and constrained, so by the size and by the order of that. That's actually obvious. How to make it the easiest way? Like that, so we define the clocks with, which is an array, an array with two items. This, the items are ordered one after another, so the order is fixed. The clock names come as well, and we expect specific names as these clock names. There are also other ways to define the arrays. So it depends on your case, this was one way. For some cases, you don't need to define the minimum items. I mean, if you have an array with, let's say, obvious items, then you can just skip the description of these items and say that you have max items too. If you just write max items too, means that min items, so the minimum number of items is the same. The reset names, in that case, have to be explicitly mentioned and described. And this is the case which I described before about the interrupts, the easiest if property is obvious, like reg, interrupts, just say max items, one, and be it. If there will be more items here, it's not the obvious case. Another typical property is syscon. So I mentioned before about the syscon compatible. Syscon compatible is a provider of a syscon, of a syscon, let's say, which is the way to access the registers from other blocks, and syscon property is the way, as a consumer of it. So there's a pretty often such syscon property, and syscon is not specific enough, it requires something more. So it should be descriptive. It should have a vendor, it should have a proper name, and it should have a description. The example there, just syscon is wrong. Please go towards this direction, so other vendor prefix, like Samsung, other sysrec is short from system registers, so some kind of descriptive name and the description. There's also a better way to show it. So this is a bit more complex example, where you, because syscon is a p-handed, so it's a kind of pointer to some other node. In that case, we use a p-handed array, and we define what type of items we expect in this array. So we expect only one item. However, this item is still an array, so it's another incident array. This item consists of two items. So one is the actual p-handle, and second is the offset, and it follows the description of entire property. So this is more complex way and more specific way to describe the syscon. I mentioned in the beginning that your schema finishes with additional properties first. So additional properties and unevaliated properties are the way, how do we control that, how do we control, how the bindings see other properties? So the properties are unexpected, how they will be handed. So usually in your case, you will just use one of them and set it as false. So additional properties false or unevaliated properties false. The simplest case will be looking exactly like this, which is pretty similar to the example from the beginning, like you list the properties, you list which properties are required, and you finish with additional properties false. And if any other property appears here, which is not listed, you will have an warning and you will have an error. There is a bit more complex way, let's say for other cases. So pretty often we reference other bindings, other schema. The example shown on the screen uses the panel dash common, so it's on some panel driver and it references common panel properties. In that case, we still can use additional properties false and this will accept only the properties listed in this particular schema. And other properties coming from the other, from this panel dash common, have to be explicitly mentioned as well. However, you don't have to describe the type, the constraints, the description from this other schema. You just have to say that it's accepted from the other one and this is expressed with this backlight true and reset GPIOs true. The description, the constraints come from the panel dash common. So the example looks like also finishes with additional properties false. And finally, we have unevaluated properties false. So this is for cases when you want to take all of the properties from the other schema. So in that case, it's pretty common for regulator.yam. Regulator.yam, Unux kernel has many, many properties and you don't want to list to which one are valid for your case or which are not, you just take all of them, like everything, give me everything. In that case, the appropriate way is to use unevaliated properties false and you don't have to describe anything different. So our first example of this panel dash common, we look like this. So we reference this panel dash common, we mention our properties specific to this device and we don't have to mention, don't have to describe the backlight, resta dpl doesn't matter because they will be coming from the panel dash common. When to use which one depends on your case. Pretty often, if you want to make it kind of extensible, then this unevaliated properties false is better approach. But if you want to make it really constrained and let's say you don't know or you don't want the other schema to be applied to you entirely, then you should use additional properties false. Depends. The stock is too short to describe all the cases. Bindings finish with the examples and we use these examples to validate the bindings themselves. Therefore, please provide always an example inside the bindings file and provide a useful example. Usually one is enough, no point to provide 10 examples, especially if they differ only by the compatible. It just doesn't prove anything. The example is intended with two or four spaces, which is a bit different than the Inuks kernel sources because everything in Inuks kernel sources is indented with a tab, so there's a difference. Preferred way is to use four spaces because it aligns nicely with opening character how this example start with. So this is how it will look like. If you have an example, hopefully you have, remove the status disabled, status okay, and this is pretty common thing that people copy the code from device resources to the example and this would be, of course, my complaint that please remove it. It's not necessary in the example. If you create a binding for a provider, like a clock provider, reset provider, so something which gives this kind of clock to others, you can skip the entirely, please skip the examples for the consumers because consumers are obvious. We have other examples of consumers. So just describe, give the example for the provider. How much time do we have? I think we still have some time. And the last thing actually is that in the device node names should be deneried. So this is also pretty common complaint from my site. The deneried node names means that it should represent some kind of class of a device like a ADC, so analog digital converter, not AD71, something, something, something. That would be it. The presentation goes further. So there are several reusable patterns for you which I collected over the time. The patterns, like how to require one property in one variant, so one of compatibles, but not in the other, how to exclude some properties, but one is required, how to exclude properties, but none of them are required. I will not go through them, just grab the PDF and find them and enjoy. There are also some references here. And that would be it. Pretty fun session. Maybe you have some questions. Is there a backstop thing? No, there is no microphone, so. What about the node names? Do these prefixes, when the name of a node so we can use the generic one, are they listed so much? So your question was whether the name of a node could have a prefix and whether there are some examples of these prefixes. Yeah, at least we get the class of the device that is always the same name. Yes, that's true. So the answer for this would be, I linked here, so device three specification has an, there's a link here if you click it, so has a generic names recommendation, has examples of the node names which you could use and also this could be a prefix for the name. And you had also second question. Yeah, about the compatibles. You are saying that you don't want the bus to appear in the compatible name, but that would make compatible being identical across different devices if we just use the subname, for instance, we would have a Vendorok comma subname for the favor, and same for the ice question, and same for the job controller, which is not very friendly from a user point of view. So far, actually, every time I had to reintroduce any compatible, I was always, I was sure that the type of device would be welcome in the compatible name, so I was a bit surprised. So your question, I'm repeating the question because the guys in internet don't hear you. So the question is that I ask not to put the type of the device in the compatible name, but actually you think that the compatible should have some type of the device name because it's useful for the people. So maybe I was not specific enough. You should not put the bus on which this device is into the compatible. So for example, don't say this SPI or I2C as that this device is on SPI bus or the device is on I2C bus. If it's an I2C controller, then I expect it's, yeah, that it's NXP, IMX8 dash I2C something, something. Okay. Next, for the verification. Anyone? Oh, great. So we were, I think, first here. Do you have advice or resources specifically with respect to graph findings? Because sometimes I find that the relationship between the devices in the board itself and the device tree binding that exists upstream, sometimes I'm working in a very strange hardware, which I cannot seem to match to the existing binding. I have made some attempts in the past to rectify these findings, but there seems to be a lot of blue discharge there with respect to the graph binding. Do you have some good resource or maybe I could be read in the device tree for education again, I'm not sure. So the question was whether I have a good example for the graph bindings or the bindings using the graphs. Specifically with respect to one. Specifically about one, too many. Therefore, unfortunately, answer is no. I can try to look and extend my presentation or maybe this will be reason to come here for the next year, but so far I don't have. Okay, thank you. Yeah. Anyone with the question? Back in there. Oh, the device can be connected in multiple buses. For example, I have, about one hour ago I was trying to find it upstairs, and I didn't, but I didn't send it yet. So, so. This one was accelerator meter at all devices, and it can be connected either to the FBI or to the I2D bus. And I was thinking that by adding this topic for the bus, it will inform the driver that because it needs the correct driver there, that which one needs to be broken to the I2D or the FBI device. So, the question is you have a accelerometer who is on the, can be on the I2D bus or SPI bus, and you actually think that adding the specific compatible for the bus would make sense in that case to help inox to prop. So, in the inox, it actually doesn't matter because the device is already on the bus. So, you just use the same and compatible, and if it's enclosed in the I2D bus, then it will be bound, it will be marched by the I2D bus stack. Therefore, it cannot be instantiated as a SPI device inside I2D bus. Therefore, the same compatible can be used for the both cases. And there are only few cases which are exceptions, and this is not the exception. I hope this answers the question. Anyone else? I think here, I saw in a hand up, no? I think everyone has solved it, though. Okay. Any more questions? Yep, one more there. I believe that Visual Studio Code has some nice plugins. Otherwise, I don't know. So, the question was whether there is a nice viewer for the YAML files. So, I would recommend Visual Studio Code. But, I'm not expert in the editors. I still use VI, so I'm happy with that. Any more questions? Oh, yeah. Yes? Example, so. So, I'll be also a parrot for the Intelian guys. So, it's not a question, it's a recommendation for me to add it to the Linux kernel. Yeah, a good idea, actually, I'm thinking about this. So, thanks for the idea. Indeed, the documentation in the kernel could be improved for this. Anything more? Yeah, please, here. So, the case is about the additional properties false when we reference other schema. So, I believe you speak about this example, right? So, this is for the case where the both two properties, so, the backlight and the reset GPIOs are already defined by either by a core schema or by the other one, so, by the panel dash common. In that case, it's accessible, it's effectively fine because the description, the type, everything comes from something else. Additional properties to true? Yeah. Yes, so, this is outside of the scope of this session. Yeah, this is useful for a few cases, for reusable bindings where you define binding which will be referenced by the other. Probably, I don't know, but probably panel dash common defines additional properties true. So, this is the case where you could use it. Brian, so, the question is whether you should always use all off or whether you should not use it. Indeed, I could add it, this is nice, typical case. So, the answer, when to use all off, when to don't use it, use always because the all off is a syntax for referencing other schema or, for example, for putting conditional. So, if something, then something. The example using it will be, I hope I have an example for this. True, so, this, if conditional could be enclosed in all off or not, both cases would work for the YAML syntax. I would propose to use that one, so, put it in all off. So, I recommend always, if you have conditional, always use all off. But then, what would you put in all off? Okay, so, that's the question. So, what would you put in the all off? So, the all off means that all off below conditions should be applied, and the condition can be, for example, other schema, so, you want other bindings, like this ref. This was this example with panel-common, so, if you want to reference other schema to be applied here, you include in the all off, if you have some if, then, else, or if, then, whatever, also put in the all off. Is this answering your question? Unavojtive properties. So, you can, you can, in the top level, you cannot reference other schema without all off. In the property name, in the property type, you could, and the property type, you don't use all off. Just copy the example schema, and base on that. The... Ha ha ha ha. But, thanks for the question, quite tricky topic. Any more questions? Yeah, here. So, the questions whether the DT binding check can look for this, dos and dons recommendations, I mentioned here. Oh, patches are welcome. I'm not sure if I would be able to code it. I mean, it's quite tricky, but, yeah, it's the DT schema, so, the tool which performs the validation of the bindings of all the stuff is written in Python. So, it's pretty, let's say, many people know Python. Yeah, but we always, I think that in this kernel would benefit from people writing more tools than not to say that in the kernel code, so, patches are welcome. Or pull request, because it works also on the GitHub, so, you can slide, slide, wing. Yeah? This is just a curiosity. Sometimes, I see in the bindings, these are compatible, which are useful for particular bindings. And sometimes, these compatible, they are embedded in, let's say, different things. So, you might have a list of items, and then there will be some other construct. Now, it's taking me, what it looks like exactly, but I have always wondered why, I don't just have a simple list of compatible things. Why is it without any different examples, plus? So, the question is, when we see the list of compatible, sometimes it's just an, for example, anum, or it's items, or one-off. So, I don't think that I have a nice example to express it, and therefore, you have to believe me on the, yeah, I would have to open some code. So, the answer to this is, depending what do you want to achieve. So, the typical case is anum, which means, like, anumerate. So, list the compatibles, which can be used independently. So, either this, or this, or this, or this, might not end. Or, it's like exclusive or, actually, so. In the other cases, you have a list of compatibles. So, like this compatible Cisco, or SuperMFD, has to be followed by a device-specific compatible. So, you have a list of two, always two. And then, therefore, use items. And sometimes, you have multiple combinations of it. And then, you have to use one-off, and then describe, specify, what is this one-off should be valid, what is the combination you expect. So, items is a list, anum is enumeration of, so, that's one, from this enumeration, and one-off is a combination of few of these options in one schema. And, I'm not sure, this example. Is one-off to contain sub-enum for sub-enum. Yes, yes. And the question in the back. In parallel. So, how do you evaluate many different DTBs? The tool that make DTBs, I mean, you run the target, make DTBs check, and it runs all possible schemas on all possible targets, or all possible DTBs, which are now compelable. And you can restrict it if it's too much. So, probably, we'll go to the beginning of the presentation to answer this question, which would be a lot of scrolling. Like in my fingers, used to clicking. So, that's the example. And this is the line here, make DTBs check, and you could skip the DT schema files, and then the check will be everything on everything. I mean, all the bindings on all the files. Question here? I think the chrono DTBs. So, the question was how to match which schema, which is a note from the DTB. Right. Yeah, in that case, the matching, yeah, this probably was the question. So, the matching, do I have the example here? Not really. So, the matching is done by compatible. So, more complicated way is, there is a keyword called SELECT, and you can find such SELECT in the bindings itself. If the SELECT is missing, there is a kind of implicit SELECT by the compatible. So, the devices schema tools are looking for the matching compatible, and when they find the matching compatible, then they, okay, so, we apply this schema. If not, then we go forward. Any more questions? Great. So, thank you for coming. Yeah, I hope it was useful, the presentation online, and yeah, have a nice day.