 So yeah, I had a slide about this actually, about me. So my talk is called Linux, I scored C and me. And I'll take care of the and me part first. He did go through it. I'm an electrical engineer by schooling, but I have a lot of previous science experience as well. I do printed circuit and board design, and some of these boards up here are boards that I helped on. Or actually, all three of the ones that are shown there are boards I did myself. And he said that I worked on the pocket beagle. I actually worked on the pocket bone, which was the predecessor to the pocket beagle. But it was kind of the stepping stone. I do a lot of Linux board support, kernel, Uboot. I do a little bit of real-time stuff and some user space, but mostly low-level. I've worked on several community initiatives, including the big board org, GSOC, 96 boards, the EALE training that's going on next door, and KeyCAD training is coming up in Reno next month. So if anybody's interested, some information about that. So first, we're going to talk about what I-squared C is, and then we're going to run through some example devices, talk a little bit about the protocol. Then we're going to skip to the I-squared C subsystem, give a little history there, some links back to different resources. I'll talk a little bit about each type of driver. Well, not all of them. I'll mention them, but there's a few other pieces. But I figure there might not be enough time to go through it all. Then I'm going to talk about instantiating devices, and there's quite a few questions about device tree in the last talk over in the other side of the wall. So I'll go over a little bit of how to instantiate devices using different interfaces, talk a little bit about the user space tools, which uses a generic character device for I-squared C, and then I'll run a little short demo on Pocket Beagle with the Baking Bits Cape. So I-squared C stands for Integrated Circuit. So it's kind of a multiple. But it was built in 1982 by Phillips. So it's been around for a long time. It's synchronous, multi-master, multi-slave interface. Not typical, but it's possible because of the type of signaling it uses. It's half duplex, meaning it can't communicate in both directions simultaneously. That's where it differs from SPI. It uses open drain signaling. So if two devices are trying to be masters at the same time, it won't cause electrical issues. It'll just follow the transaction. There's the arbitration to determine which master is which. But for the majority of cases, you're a single master of multiple slaves. You only have two wires for signaling, SDA and SDL. They are usually 100-kilometer signaling speed, not super fast. There is a link down there for Wikipedia, which goes on and on about the protocol. I really recommend taking a look at that. They did a really good job on that article. But here's some of the highlights. So it's a seven bus addressing protocol, at least originally. And the original spec also called out 100-kilor. And then progressively got faster and faster. So version one added foreign fast mode with 10-bit addressing, which is part of the protocol. And then they kept boosting it up. The ultra-fast is actually unidirectional, being that it uses push-pull instead of open drain. That means it'll drive both low and high states. And so it's just one way. And then Intel came up with this thing called SMBus, which is a subset of iSquared C, which is used on motherboards, particularly, for monitoring devices, temperature. They constrained the protocol electrically. And they added some optional software addressing address resolution. So iSquared C, it doesn't really have a way of kind of broadcasting back what's on the bus. So that's kind of the limitation of the iSquared C. And SMBus optionally takes care of that. So here's some example devices that would use iSquared C. We got real-time clocks, eProms, analog converters, which I use quite a bit, sensors, temperature, pressure, accelerometer, et cetera. Microcontrollers can actually be master or slave. And we'll talk a little bit about that. What are the differences? There's touchscreen controllers, usually four-wire resistive, if they're iSquared C. TPI-O controllers. And the monitors and TVs have these things called DCD, which is kind of iSquared C for detecting the parameters of the monitor when you plug it in, so that it automatically works. So here's a few sample circuits that I actually grafted from a couple of my designs. This here up top is an accelerometer. That's actually what was on this guy. There's an accelerometer on here. And I will show you guys accessing that accelerometer towards the end. This guy down here is a PWM controller that's iSquared C. And it was on this board called RoboMessy. And it's also on some Adafruit boards, different breakout boards, so you can drive up to 16 servos from the two iSquared C lines. The important thing about iSquared C is you have to have at least the pull-up resistors on there. You'll see that there's pull-up resistors there. They're up to 3.3. And the signaling voltage is dependent on the controller you're interfacing with. And if you don't put those resistors on there, it just won't work. It won't pull up, so the open collector could pull it down. And if you don't put the right values, then you'll also have problems because of the rise times. There's a really good talk by Dave Anders. It goes into detail about how the mechanism works, so I'm not going to get too far into the hardware stuff. If you're interested, I can point you to that. I was going to add a link, but I forgot. OK, so here's a little picture of the protocol. This is just the addressing in 7-bit mode. It's a basic transaction. So what happens is the lines will fall low in a specific sequence to signal the start of transmission. It's called the start bit, really just a transition sequence. And then the address bit is shifted out along with a read-write signal, which will be 1 for read, 0 for write. And then an act bit will be either 0 or 1 based on the acknowledgment. And then the data comes out, if it's a read, the slave interface will send the data back on the lines. If it's a write, the master will send the data out on the same line. So it's not a bidirectional communication, but it goes either way. So it goes from the host to the slave during a write. And then you'll have a little bit from the host. And then the rest comes back from the slave with a read. And then there's another transmission signaling the end. Now, typically, this data is actually per device. There's a definition of the internal chip addressing, which will be what register internally. And then it'll have the values you want to send to that register or what is read back from it. So there is a bit more to the protocol, but it wouldn't fit on the slide with being able to see it all. So here we'll get to the Linux portion of it. The early implementations were pretty early on in the 2.x era. And there was one out of tree, and one was kind of tied. I think the out of tree one was the LM sensors. But either way, eventually, Greg Groharman came along and kind of pulled it towards the new developing device model, which came out in the 2.5, early 2.6 era. And then David Bramble and John Delvere did the standard device model port in 2.6. And a lot of things happened since then. I can't really go through everything. But then Wolfram is the current maintainer. We'll talk about how you would get to a hold of the maintainer in a minute here. So here's an overview of what the sub-system looks like. There's a couple of pieces that are required for the overall system. You have the core peripheral inside of the SOC, a Linux-capable processor. We'll have a peripheral controller internally. And this thing called the adapter will allow the core portion of the iSquad C sub-system to talk to the host controller's peripheral adapter or whatever. And then there's an algorithm that's usually built for each host to have an adapter, which will pretty much pass along a function that allows the core to talk to the hardware, essentially. And then on the top side, which is where most people are interested, you have the drivers, the client, and the driver driver. It's kind of a silly name, but we'll go into that a little bit. So the slave device has an instantiation. It talks to the iSquad C core, which abstracts the SOC's peripheral interface so that it's the same across different platforms. So your iSquad C driver shall work across the whole iSquad C sub-system, and that's part of the device model. And then you just map it and go. There is mention of iSquad C dev, which is a user-space interface, so we'll talk about it towards the end. The Linux iSquad C sub-system mailing list, and if you're a kernel developer, you want to get to know how to use the mailing list. So this is actually straight from the page I just pasted it in. You can subscribe to the mailing list for the link there, and there's the web interface for the mailing list. And the mailing list is your entry point into the sub- system for mainline. So if you wanted to do mainline development, you'll have to go through the sub-system, which the sub-system maintainer will monitor. And then he has his own separate Git repository, which he'll apply the patches that you send to him. And then he sends them up with merge requests to Greg Krahartman, which eventually goes up the stream to the mainline kernel. So this is going to talk a bit more about the algorithm and adapter. So the algorithm driver contains general code that can be used for a whole class of iSquad adapters. This is actually directly from the documentation, which I have a link down here. I can actually show you that towards the end if we have time of the actual documentation. And each specific adapter driver depends on one algorithm or includes its own implementation, which I stated previously. And then for device drivers, they have it split to driver and client. And it actually says that right in the documentation, a driver driver. It's kind of silly, but that's what they call it. But this is essentially the iSquad C device driver, where you'll contribute if you wanted to add a new touchscreen controller. You'd create one of these type of device driver for iSquad C and iSquad C subsystems. The protocol drivers are spread throughout the driver's subsystems. They're not contained to any one specific subsystem. So if you have an analog converter, you'd be in the IIO subsystem or HW mon, hardware monitor. So the host controllers are actually in a specific driver directory, driver's iSquad C in the kernel source, where these are everywhere. They're across the board. Any kind of device you can imagine that has iSquad C will be spread across the kernel drivers. I'm going to talk a little bit about this, but I don't have a whole lot of time to go into it. Recently, I think 2014, iSquad C maintainer added slave support. What that means is if your controller supports it, your Linux SLC can actually act as a slave instead of a host controller. That means you could actually talk from one, from a Linux SLC to another SLC, and it'll emulate a slave device. And there's some bindings that are required. This is an assistive interface that you use to poke in, hey, I want this particular type of slave. The slave interface documentation is down here at the bottom. And there's a nice presentation from the iSquad C maintainer down there at the bottom. He goes through in pretty much, pretty good detail. So I haven't really covered the anatomy of a driver. I didn't think I'd have enough time, but maybe I can show you at the end. But here's how we instantiate devices. So one method is the device tree, and this is preferred method for ARM and other device tree compatible devices. So the device tree binding will say, hey, I have this particular device, which is specified by the register and the compatible string. So the register is the iSquad C address. And the compatible string is what binds the driver to the registration here. I can show you inside of one of the drivers where that is. And then say you have multiple devices on the bus, then I'll just add further registrations. This one is special because it's an iSquad C controller for GPIO. So you have to specify that it's a GPI controller. There's actually a GPIO controller on the bacon bits, but it's SPI control. OK, now back in the day before the transition to the device tree, when I first started, there was a thing called platform devices. Platform devices that are a platform bus is still used, but it's abstracted a little bit. This was actually a physical C file in ARM, Mock, whatever architecture, and then a board file. The board file contained the registration for different devices, and it was a C code. I don't really use this so much anymore. There are maybe a few cases where this is still around, but they kind of transitioned away from it over time. And there's a way to do instantiating from user space, which is a neat feature, as long as your driver supports it. And you echo the driver name, address, and you have a SysBus iSquad C devices. And then you have, for each bus that you have on your system, you'll have a different iSquad C dash, whatever, added new device. I didn't want to break it down too much. If you're interested in how to do that, there's a whole, for all the instantiation methods, there's a documentation in the kernel source directory. OK. So we have some user space tools that are used, kind of abused at times, a character device, which is kind of an abstract device, which can access pretty much anything on an iSquad C bus. The device note will come up, dev iSquad C dash, whatever the bus number is. And then you have an iO control that sets a slave address, which was the address and the slave protocol. And then you can use simple read and write mechanism. So you can say, hey, write this register, or read from this register. There's an encapsulated version called iSquad C SM bus rewrite. If you don't understand that notation, I can break it down for you. Well, the protocol depends on the device you're accessing. But typically, you send the address of the device, which is the iSquad C address. Then you have an internal register address, which is sent as a set of data. So you'll send the address, and sometimes there's other bits involved. It depends on the controller on the slave. So you'll just send a sequence of bytes to it. And the sequence of bytes will determine what address register internally is address. So that's part of the protocol, essentially. What's that? No, the recommand is kind of raw, whereas this will actually break it down into separate. It'll actually do a little bit more for you. And the dev interface is also linked down here at the bottom. I know I've kind of pushed everything off to the links, but this is more of a higher level kind of thing. And you can go and kind of dig in if you're really interested. These instructions are pretty important for the iSquad C user space implementation. There's a whole slew of defines. And I didn't want to have to put them on the slides. They'd be slide after slide. And then there's some tools that use that interface. One is called I2C detect, which it'll go out at each address and kind of see if anything acknowledges. And it'll print it out on the screen in nice little tabular form. It will ask you if you really want to do this when you use it. It's kind of real kind of tricky about it. This is used mostly for early testing. And I'll actually show a demo of that, as well as a demo of a driver running here at the end. OK. Here's the demo. Of course, this is always where the problems start, right? Let me make sure. First, we've got to get the council up there, huh? Does that probably not large enough, is it? I'm going to plug in the bacon bits, keep, leave the serial debug header, because it's just what I'm used to. I'm actually currently in a minicom instance, I believe. Oh, that's the wrong header. I should know this. There we go. Oh, I don't have this SD card plugged in. So for the first, the demo means that the standard Debian image, being up the kernel, Debian image takes a little while, because it's a full blown OS, like all the gadgets and what have you. I have a build root file system that I'm going to boot up next for the next portion of the demo. It boots a lot faster. That's why we don't do live demos. All right, Debian. OK, so we're prompt here or not. Can you see the prompt? There it is, OK. So I'm going to show an example of, oh, my notes disappeared. Oh, wait, I'm guessing it's just down further. Hold on. So I'm going to use iSport-C Utils to access the accelerometer on the board directly. And this is good for when you're first trying your hardware, you want to say, hey, is this hardware working? This will give you a real good idea real fast. So first, let's do an iSport-C Detect and see what comes up. If I take that, it tails off the front there. Detect, all right. And then I think it's on bus two. Dash, and then dash. It tells you what protocols are supported by the bus. It tells you the different adapters that you have. Of course, I don't remember the command off the top of my head again. Either way, dash R, there it is. The last one you try, of course. You can tell I don't use this often, but it's very useful when you're first start. You see here it says one C. That's the address of the device, the accelerometer that's on the board. So now I'm going to poke at the registers internally on that device. So you set it up for sampling on the converter. This is going to poke a register internal. So this TLA is the internal register on the iSport-C device. And this is the value that I want to write to that register. That one turns the, it's shutting off the conversion, actually. And this one here is configuring the conversion to G. And then we got, I'll do that right. And the last piece is enabling the conversion. Yes. All right, so I've written out some registers and it's doing the conversion internally. And what I'm going to do is I'm going to use the iSport-C dub command, which is really just a read across a bunch of registers, a watch, or a wild one, to show that it shows the values as it kind of moves around. OK, so you see how those registers are kind of wiggling around? Those are like the raw hex counts of the different accesses of the accelerometer. So if I move around the device, it'll change the values that are coming up down there. It's not really readable in this form, at least not easily readable. It's assigned values, so you'll see that you'll have FE, F, whatever, and then the number. For this one it's a 10-bit conversion. But if you're going to really use an iSport-C device, you should make a real driver. So what I'm going to demonstrate next is the use of an industrial IEO or IIO driver to access the same device. So I was going to put it on there directly, but I kind of ended up with this one. This is a build root file system. OK, you see that? Blinding fast. All right, so let's log into this guy. All right, so tried to access the same device on this build because it has a registration. It won't allow you to access it with the other tool. So if I were to do this iSport-C set on here, it'll probably block at me. Kind of access device or resource busy. I mean, that's driver's bound to the iSport-C bus at that address. And then let's go back into where the registration comes through, this iSport-C. And we have a devices directory. So anything that's registered will show up here. And you see there's the second bus, 001 Charlie. That's our device. So that means the platform registered, there was a registration for this, which is in the device tree. And I can show you guys that if you'd like to see it. So it tells you a bit about the device. So you see that it's an industrial iO device. So the thing about the device model is it's kind of recursive. And so if you register something on iSport-C bus and it comes up as a different type of bus, it can kind of go down from there. So iIO is in SIS and now bus. And there's a whole other talk about how iIO works. We're just going to show you that the device is attached here. So you see there up at the top, you'll have the accelerometer scale and then accelerometer readings. They're all broken down into virtual files. So if you cat those files, I'll give you the raw account. It's a signed account. So if we do a y reading, I guess y would be this too. And that shows you that it's orientated either right side up or up. And then you have one for each axis. I created this little special script that accesses the accelerometer. So let's take a look at it first. OK. And what it's doing is it's catting those files into variables and then rendering them out to the screen. But I'm not really complicated. So then we got auto-test. And there you go. So you can watch it get in alive. As I move it around, you can see the different accesses change. So the protocol driver in this case is the industrial IO driver. The adapter driver is an old map controller driver that's based on the SOC on the bottom here. So I guess I could show you some of the various pieces if we have some time. Do we have some time? Yeah, it looks like we have plenty of time. So let's take a look at some of the different pieces here. We read that. OK, that's the builder directly. So a lot of the links I showed were hyperlinks. But also all the documentation is actually in the source tree directly. This is the kernel tree here. And you'll see I have multiple different sub-repose. Origin is the mainline kernel here. And then documentation, let's quote C. And a lot of the text that I just scammed out of some of these files. If you want to get into more detail on anything particular, just go in here and say, oh, I want to learn more about how the slave interface works. There's a separate file for that. One thing that I didn't mention was multiplexers or muxes. This allows multiple devices of the same type to be on the same bus, but multiplexed. This is useful because the address space of I2C is quite limited. And there are going to be times when they overlap. Or you want to have more of the same device. Sometimes we'll just use pins to change the address slightly. But when you're on that option, you use a multiplexer. So anything that you're interested in should be here. Make this a little bigger. And then let's go to the registration. I guess that would be for the platform registration for this system. Use the device tree. This is the controller registration I'll be in here. There's I2C2, and there's I2C2. And what this does is it maps a compatible string, which will be in the driver. And it gives you the registers, the platform registers, our memory map registers inside of the SoC. And this is used to pass to the driver through the instantiation. These are kind of fixed. You usually have to worry about this. If you have a system that has good Linux support, this will already be taken care of for you. But then, which one? HW Mod. HW Mod? Yeah, factory or TI combo, HW Mod, that's free. Yeah, I'm not real sure on that one. It's a TI specific, see how it has TI in the front. So you'd have to look at the driver and see how it parses that, what it does with it. So the driver for the I2C2C, so this is drivers and then anything that's a bus or an adapter would be in the bus's directory. So every SoC or implementation is going to be for the adapter side will be in here. And the TI1 would be, I think it's I2C OMAP. You'll have a compatible string here. I guess it would be down through the end. OK, so it's a platform driver, so there's going to be a lot of boilerplate code here. And then you have the open from our match table here. And you see you'll have the compatible strings. And when it probes, when it sees a match, a compatible match, it'll probe the driver. And this data will be passed, so this data will give you a little bit more information. This isn't necessary for all different controllers, but they like to combine the controllers for different series of processors into the same driver to eliminate redundancy in the code. And then you have, that gives you that, tells you what's going on with that particular device. And then there's quite a bit involved in making an adapter driver, which I really couldn't cover in one presentation. Maybe it could be a separate session. But there's going to be callback functions that are called from the iSquad C core driver to accomplish what you need to. There's a lot involved. So let's quit out of that one. And then let's look at the protocol or driver in IIO. It was an accelerometer, or whatever it was called. Yeah, the name of the accelerometer, it's MMA something. Now that I'm thinking about it, aren't they 84-52? There's a series of them that are going to be supported by it. And 84-53 is the one that we're using on the Reb1 of the Cape. This is the one that was used originally. But we leveraged stock from GHI. So we had to go down to this guy, but no big deal. And so this is the driver that's quite a lot of code as well. Let's go to the end, where the important stuff is, I guess. So here's your typical iSquad C driver. We'll have this driver struct. And it'll have some callbacks here and pointers to tables that are useful in matching the device. So again, there's a device tree pointer table. And that'll match with the device tree entry. So we put this free scale underscore 84-53 into the device tree under the iSquad C sub-note. And then off it goes. And it'll probe that device on boot if the driver's loaded. And if the driver's loaded dynamically, it'll detect and load. And then what will happen is the iSquad C probe will be called. And the iSquad C client struct will pass relevant information down to this guy. And then you'll have per controller data. So for each, you'll have to allocate a little bit of memory. DevM-IO-IO device alloc is specific to the IIO. Anything that starts with DevM is nice, because you won't have to do a free call in the remove function. It'll just do that magically through the course. And then you've got your basic sum bus read byte data. Who am I? And then it figures out who it is and attaches. Yeah, it's going to tell you a little bit about the device. So it's a register internal to the accelerometer. And then these are just kind of a defiance to say, hey, which register reads out this value? And it can be slightly different based on the different types of devices. But you get the idea. Back to the bottom. And this table here is you can use for dynamic probing and platform registration outside of device tree. Yeah, the platform files. If you guys would like to see an example of the platform files, this is kind of legacy. But they used to end up in Linux. Arc, Arc, ARM. A lot of them in fact are out, especially in ARM, because it was quite a mess. And Linux 12.0 got really mad. And they fixed it. That's a OMAP 2, I guess. There's not going to be a whole lot of examples here, but there is still a platform file. There was one for each different board. And here I got it. It just gets a little out of hand after a while. But inside of these, they'll have that platform registration, which I showed in the slides earlier. So I guess that's enough for the demo. We can move on to the questions now that we have like 10 minutes left. Device. Yeah, it's already instantiated. So I don't know if it doesn't work for all drivers. But it depends on the probe function. So let's go back into the driver. This particular driver, I think Jason had problems getting it dynamically allocated or whatever. So he had to use a device tree overlay, I think. The problem was they didn't have any code for handling that. So it was either you had a device tree registration or it just wasn't there in the driver. I suppose I could show you that. Drivers, IO, colorometer. What time? Overlays are kind of new, but oh, is it? I had to CD twice, yeah. Distracted typing again. There we go, 84, 2. And then we go down to the probe function. And then you see this device tree. This is the open firmware device match. And you see how it says, if not match, unknown device model. So it doesn't really expect anything but a device tree for this particular driver. Every more code, platform code. And I have a little session about I-squared-C that will cover a bit more of this detail tomorrow in the embedded ALE. If you're registered, you can come and see that as well. So I guess questions? Oh, it's pretty different. This is a busy box image, and it's very small. It could be smaller, actually, but I'm not free to H, I was free to K, I think, two Ks. There we go. We don't want to megabytes, kilobytes, gigabytes. So we're only using 13 megs. Not bad. It can be up there, depending on what you have running. The Debian stock image does run a lot of web services and stuff. So really, this is about as pretty bare bones. It doesn't have a whole lot of features installed. So BuildRid is good for kind of a small footprint type of builds. Anybody else? Sure. Yeah, that would be pretty tricky, because these hex addresses aren't unique in that they can be assigned to multiple devices. So you could have two separate, completely different types of iSquizzie device that'll have the same address. But you could, perhaps, maybe grep through the driver code. It's really not easy. Yeah, it's kind of tricky. I guess the other way around would be trying to find the schematic for the board that you're working on. And if you're doing boards before, you usually have that. If it's still something you can't figure out, then I guess you kind of go upstream to the hardware manufacturer and see what's going on. I'll get one back here first. Yeah, hi. I apologize. This might be a pretty big question. I'm not too familiar with iSquizzie, but the example that you have with the accelerometer, it seems like that it's just kind of streaming data over the iSquizzie bus. It seems like that. But what I'm doing is I'm actually polling their device continually. So it is polling. That was my question. Yeah. But is it always a polling type of your thing, or is there is streaming, and is there is what kind of arbitration is there? Yeah. Do you have multiple devices on a bus? Yeah. If there's multiple devices on the bus, they won't talk to the master unless they're addressed. So that's a way of arbitrating between. And there's really no streaming involved. You have to, from the master, you have to say, hey, read from this specific device. It's not going to stream because otherwise it would cause all sorts of collisions on the bus. When you show the accelerometer, there's a register on there with those types of who am I. Yeah. That's something specific to that accelerometer, right? I was wondering, let's say I'm trying to create some iSquizzie purpose. Is there like some kind of convention for that particular register? Is it what am I registered, or does it show that? Yeah. We'd have to dig into the protocol a little bit. There probably is something like that. The who am I register might be standard. But I don't go that far into the spec usually. I just try to get the device at hand working. The link for Wikipedia has some pretty detailed explanation of the protocol. And it also has, from their link spec to the actual spec, where you might be able to find something like that for iSquizzie protocol. That's not like a really standardized kind of thing. I mean, you do it that way now. The interface over there says read. It doesn't even pass a register to it. So I'm not sure it's like, is this a hard and fast standard? Or is it the people of more or less kind of doing things in a particular way? But not everybody is doing it the same way. The protocol is defined. And the address of the device has to be specified before you do a read. No, the registers on the device itself. The registers on its device are really dependent on the implementation of the device itself. That's right. There's no standard to close. Like, you know, register number three should be the what am I, right? Yeah, there is no direct standardization, I don't think. But there is kind of a guideline so that you can use basically the same kind of register mapping from one device to the next. So if you have like, from the same vendor, you have like, say, from TI, you have a touchscreen controller. And then you have an ADC accessing the registers. The address probably would be in the same place. Because they're probably going to reuse the internal hardware slave core or whatever. But it's really up to the datasheet to determine the protocol beyond the addressing of the device itself. What's the algorithm? What are some of the different algorithms? Algorithms? They're like, I don't know. So it's kind of standard algorithm. Let me try to get a feel for what you're asking. Like, are there different types of algorithms that are used for I can imagine that there is one. For the protocol, I didn't know if there was different variation for it. Yeah, I think there are just, I don't know, them off the top of my head. Is it similar to how like, you know, SDI has different settings, like the writing of all the edges and things like that? Yeah, it wouldn't be quite like that. There would be other types of parameters. Like the protocol would maybe determine the sequence of bytes or whatever. But I usually, the protocol is really just saying, hey, jam these two lines. The adapter is pretty much saying, hey, call back to this function, and then that function will do what you want it to do, essentially. There's not a whole bunch to it. If I was an I-squared C expert or a Linux kernel I-squared C expert, I'd probably give you a better answer on that. But I just kind of get things working, essentially. Sometimes when you look at the ICC adapter, and how that corresponds to the peripherals that you're trying to see, that I can see peripherals. Sometimes we're not just saying, like, you might be dealing with, like, on the chip, like, I can see peripheral number one. But then, like, in the last step, I can see a few peripherals. Yeah, there's a, do you mean the name of the device? Yeah. There is a mapping called aliases in the device tree file, which will determine the order. If you don't specify it, it'll kind of pick the order for you. I could probably show you that. I'm guessing it was probably a pretty long time. But let's check it out. OK, here's your aliases list. And this will determine the order. So it's pretty straightforward on this particular device. There's just one to one mapping. But you can change, you could say, if you wanted the peripheral controller that's mapped at I-squared C1 on this, come up as I-squared C0. It really just depends on this alias here. And that it's useful for the ordering of the serial ports as well, and the USB controllers, et cetera, ethernet. So that's used to kind of determine the order in the device, essentially. It's completely possible. So for example, if I can add my two little kits of C5 more I-squared C1 buses being used on the board, buses that just aren't run up to the user state. If you don't register in the device tree and enable it, it's not going to show up. So in the top level DTS, you'll have one. And this is the DTSI, which is kind of like for the SOC. And you'll notice that I-squared C0, you have the status equals disabled right here. So if you're not mapping a device to it, then this will stay disabled and it won't show up in the devices. If you have the device tree file for your specific device, then you can probably enable it. It's just a matter of getting to it. Another thing to worry about is the pin boxing though. So there may be five or six controllers, but they're all coming out through a limited number of pins. So they have to be multiplexed out to the SOC pins. So if you want to use them as I-squared C0, you got to make sure they don't contend with anything and they're actually broken out to pads somewhere. And then you have to set the multiplexer so that it sets that pin for that specific function. And then you can enable it and go essentially. So it's kind of like there's a few hurdles, but you could do something like that, yes. Yeah. So you're kind of piggybacking onto another bus? Yeah. OK. Yeah, probably some kind of maybe for a firmware or something that they don't want you messing with. Yeah, that either happens earlier on in the boot and then they don't expose the interfaces to the user space or to even to the kernel. It depends on how it's mapped in the device tree. Yeah, if you have mainline support for your device, I'm not sure about that particular one, but one thing I didn't bring up is pin boxing can be kind of one of the first things. Like if I can't get my device working, first thing you do is determine if your pin boxing is correct. From there, you got to determine if you have the pull-ups on the lines and not in multiple places, not too small of values. And then from there, it's just kind of software pretty much.