We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Porting U-Boot to a Modular Device

00:00

Formal Metadata

Title
Porting U-Boot to a Modular Device
Subtitle
Booting Linux via U-Boot on a board which can be composed of several different modules
Title of Series
Number of Parts
561
Author
License
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Currently, Das U-Boot and Linux use device tree to specify how the different hardware components are connected to each other on a board. If a board has a way via which the user can plug in another hardware component, unless we are talking about universal buses like USB or SDIO, the device tree has to be updated to corresponding to the change. There are several ways how this issue can be solved. One may, for example, have a different device tree for each configuration, or one can use device tree overlays. But what if you have a device which can, via one bus, connect several devices, and these may or may not be of the same kind? The number of different device trees would grow rapidly, and one could not use the same device tree overlay when the same device is connected more than one time without editing the overlay. Fortunately U-Boot can fixup the loaded device tree before booting. In this talk we shall describe how we used this fixup feature (hopefully in an elegant and upstreamable way) to solve this issue on Turris MOX, a modular SOHO router.
10
58
80
111
137
Thumbnail
15:21
159
Thumbnail
18:51
168
Thumbnail
26:18
213
221
Thumbnail
15:22
234
Thumbnail
49:51
248
Thumbnail
23:06
256
268
283
Thumbnail
28:38
313
Thumbnail
1:00:10
318
Thumbnail
21:35
343
345
Thumbnail
36:13
353
Thumbnail
18:44
369
370
373
Thumbnail
44:37
396
Thumbnail
28:21
413
Thumbnail
16:24
439
455
Thumbnail
25:10
529
Thumbnail
15:36
535
Thumbnail
28:04
552
Modul <Datentyp>BootingWhiteboardModul <Software>Software developerStudent's t-testComponent-based software engineeringConnected spaceAnglePCI ExpressNetwork topologyTopologyShift registerOverlay-NetzVertex (graph theory)Parameter (computer programming)Modul <Software>Router (computing)Connectivity (graph theory)Operating systemCategory of beingKernel (computing)Network topologyGraph theoryGraph (mathematics)Overlay-NetzElectronic mailing listBinary codeExpressionCycle (graph theory)WhiteboardNormal (geometry)BootingType theoryPCI ExpressPlastikkarteFlow separationPresentation of a groupContent (media)Bus (computing)MultiplicationOcean currentDisk read-and-write headParameter (computer programming)NeuroinformatikDifferent (Kate Ryan album)Shift operatorComputer scienceMultiplication signTopologyDevice driverInterrupt <Informatik>Standard deviationSystem identificationShift registerConnected spaceDirectory serviceBarrelled spaceProjective planeInterface (computing)TorusMathematicsMereologyComputer animation
PCI ExpressConnected spaceTopologyModul <Datentyp>Shift registerNetwork topologyWhiteboardFunction (mathematics)Modul <Software>CodeLine (geometry)Vertex (graph theory)BootingParameter (computer programming)Configuration spaceDefault (computer science)TranscodierungDefault (computer science)Line (geometry)Functional (mathematics)CodePointer (computer programming)AdditionDifferent (Kate Ryan album)BootingKernel (computing)TopologyScripting languagePatch (Unix)WhiteboardMathematicsNumberOverlay-NetzParameter (computer programming)Network topologyError messageElectronic mailing listModul <Software>ResultantPosition operatorEmailSlide ruleBefehlsprozessorValue-added networkConfiguration spaceMultiplication signOperating systemLatent heatSpecial functionsSpacetimeMetric systemSource codeConnected spaceOperator (mathematics)Computer animation
CodeDevice driverKernel (computing)TelecommunicationImplementationModul <Software>BootingLine (geometry)Service (economics)MathematicsModul <Software>Device driverCodeBefehlsprozessorImplementationNetwork topologyPoint (geometry)TelecommunicationProper mapKernel (computing)Multiplication signRevision control2 (number)Presentation of a groupSlide ruleRepository (publishing)Software developerPointer (computer programming)Overlay-NetzWhiteboardCorrespondence (mathematics)Booting1 (number)Computer animation
Computer animation
Transcript: English(auto-generated)
Good afternoon. My name is Marek Behun and I'm going to talk about what I have been working on for the last few months at work. That is about porting U-Boot to a modular device, a device into which different modules
can be plugged, like USB or something like that, but it doesn't work like USB so a different approach had to be chosen.
Here we have the contents of the presentation. First about me. I was born in Slovakia, 1991, using Linux from 14. Currently I am studying computer science in Prague and for the last two years I have been
working at CZNIC on Project Turis. The problem which this presentation is about was solved for Turismox.
What is device tree? I don't know how people here are proficient in U-Boot, so let's hope this is not too much for you. The operating system kernel has to know how different computer parts, components on
a board are connected to each other. For this, the standard for device tree was created.
Device tree is a, as the name suggests, is a graph in which each node represents one device, has properties about what type of device it is, which driver should be used and which interrupt lines are connected to the device and so on.
Actually it's not a tree in graph theory because the edges can form a directed cycle sometimes, so it should be maybe called the device graph.
Well, what if some components are pluggable? For example, USB is pluggable into each device, which supports USB.
If you have a router or a Raspberry Pi, you can also plug PCI cards, PCI express cards in computers, and nowadays SDIO can be used. We can plug a Wi-Fi card into the slot for SD cards.
What if the components which we are talking about aren't plugged via such a bus that supports such a change?
Then device tree has to be changed. If you have USB devices, you do not have to tell the operating system which USB device is connected because USB supports self-identification, so the operating system can read from the
USB device what type of device it is, and also from SDIO and PCI express. But if you have, for example, Raspberry Pi with the HIFI berry shield, or if you have, there are many kinds of shield, now I have read about TV head for Raspberry Pi,
if you have something like that, then you have to change the device tree with which U-Boot boots Linux.
And our device exposes several interfaces, like USB, PCI, and Ethernet via one connector.
There are several different modules which can be connected to the device, and they can also be connected in, some of them can be connected multiple times. For example, the switch module can be connected more times, and then you have multiple ports, Ethernet ports.
The topology of how these modules are connected can be read via SPI, via a SPI shift register. The problem I was solving was how to let the kernel know in an elegant way which modules
are connected. Normally, for this kind of thing, there are device tree overlays.
Device tree overlays are a special kind of device trees, device tree binaries, which the bootloader can overlay over a normal device tree, and it will somehow change
the original device tree binary. For example, it will add some devices or create some edges in the device tree, so that the kernel will know that something is connected additionally.
Here is a screenshot of a listing of all the different device tree overlays supported by Raspberry Pi. If you look into the slash boot directory, slash overlays on your Raspberry Pi, you can find all these overlays and more.
Here are only 14 listed. The question is, can we use device tree overlays for each module on our board? The answer is no, because the parameters for the device tree for each module are
dependent not only on which module this is, but also where in the topology it is connected. If it is in the second place after some different module, then the parameters have
to change for this module. For example, if I have a module for the fourth one, for an SFP cage, it's dependent on if it is, for example, in the third place or if it is directly connected to the
CPU module, because there are GPIOs on the SFP cage, and the GPIOs can be read via the SPI line via which the topology is also read.
So we can't use device tree overlays for this problem, really. At first I actually used device tree overlays, but as you can see, the number of different
device trees, device tree overlays, grows rapidly because each configuration has its own overlay. For example, if I connect three switches with chipset Peridot, then I have to have
different device tree overlays as when I connect only two. This will grow more rapidly because the SFP module will also multiply the number
by two. So we could use device tree overlays, but it's not very nice and elegant. Fortunately, U-Boot has this feature that each board-specific code can use.
So for different boards in the U-Boot source, you have a special code for booting them, and one of the functions you can write for your board is FT board setup, which
will pass you the pointer to the device tree loaded by the user or by the script booting the operating system, and in this function you can change the device tree, fix it or
something, remove nodes, create nodes, and so on. At first I tried to create whole nodes for each module in this function.
The main device tree for the kernel didn't contain nodes for the modules, only for the CPU module, not for the pluggable modules. And my code in FT board setup created all the nodes for all the connected modules.
But the result was almost 1,500 lines of ugly C code. Ugly. If I wanted to check for every possible error, then it was ugly.
Many times it was the same thing, but something was different, so you couldn't write a special function for everything. It couldn't be squashed by using functions.
I asked myself how to do it so that the code will look more nice, and I have decided
that the right metric was minimizing the number of changes that the code in U-Boot has to do in the device tree so that it can boot correctly the device.
I decided that I will write nodes for every module inside the main device tree in Linux, but I will use status disabled for those nodes so that the kernel will ignore them on default. And on boot time, U-Boot in this FT board setup function will just look at the SPI
line, discover which modules are connected, and it will just change status to OK on those nodes which are connected.
And also sometimes it has to change something more because of what I talked about some slides ago, because some modules need special configuration because of the position where they are.
The result from this was only under 250 lines of additional C code. I have a screenshot here.
It looks, in my opinion, a lot nicer than the original 1500 lines. We also add 600 lines of device tree code in the main device tree in kernel, and the
status of this is that the patches, some of them are already reviewed on kernel mailing lists, so it looks like it will be accepted into kernel as well, and it was already reviewed
in U-Boot. Here in this screenshot you can see that I have to change the name of the node which
exposes GPIOs for the SFP module.
The advantages and disadvantages of this solution, in my opinion, the advantages are that there is less C code, new C code. It is also more readable.
I actually had the 1500 lines of code a few months ago, but I didn't know that I will be making this presentation, and I removed it. But if I had it, you would see that the code was ugly.
Another advantage, in my opinion, is that when some developer makes a change in a driver in the kernel, for example for the switch in the DSA subsystem, and this change would
have to also change device trees somehow. Then if the whole device tree is in the kernel, in the kernel repository, then they will also change it and I won't have to change it on my own.
The disadvantages, well, we are not using overlays and they are meant for this kind of thing, but they couldn't be used in an efficient way, so I decided not to use them.
A bonus slide, one problem which I had to solve, which I needed to find a solution for, on our board, SerDes lines, the driver for the initialization of SerDes lines is
loaded before SPI driver. This means that SerDes lines are initialized before, and when I initialize the SerDes
lines, I have to know the speed for each line. For example, if SFP module is connected, then the corresponding SerDes line has to be for one gigabit, but when switch module is connected, the corresponding line has
to be at 2.5 gigabits per second. When the SerDes initialization is done before the SPI, then I cannot know which module is connected.
There were two solutions for this. One solution was to write a proper driver for SerDes initialization. By proper, I mean that the SFP node in your boot, in the device 3, should have a pointer
to the SerDes line, and the driver then would have known which speed to use.
If it is connected to the SFP line in the device 3, it would have known that it should enable the SerDes line on one gigabit. If the switch node is connected, then it would have known it should enable it on 2.5.
But writing, completely rewriting the SerDes initiation code was too much work for my time. I decided that I will solve this problem by writing my own tiny implementation of
SPI communication. It is only 35 lines of code. I write to some registers directly on the CPU and then read some registers and I have
read the first 10 bytes from the SPI so that then I know which modules are connected. This solution is not very elegant because there is a proper implementation of SPI communication
in your boot and I had to write my own. So we discovered the duplication, but this can be removed when we have the correct SerDes
installation driver. Thank you. Okay, that's all from me. Any questions?
Yes? Is it possible to get some kind of notification when another device is attached? Our device does not support hot plugging, only booting.
I have actually talked today with a colleague if it was possible, if it were possible. The problem is that our device, if you connect something, the voltage will drop for a little time and the CPU will reset. But we have been thinking about if we could do hot plugging and kernel supports device
is mostly changing online, so we would have to work on it. I would have to write drivers for this, but it could be working.
Our device does not support it. Or not. The board would have to be changed. Maybe next version. Okay, thank you. Welcome. Questions?
Okay.