Linux Plumbers Conference: New hardware with modern I2C address conflicts

Earlier this week I attended Linux Plumbers Conference 2019. Among the sessions I attended, the most relevant to me has been the BoF session led by I2C Linux maintainer Wolfram Sang: “New hardware with modern I2C address conflicts“.

The goal was to discuss changes needed to the Linux kernel I2C subsystem to support video serializer and deserializer chipsets (“serdes”). These chips allow to access the I2C bus on multiple remote camera or display modules from a single I2C master controller on the main SoC.

Following is a brief report of the discussion.

Wolfram’s intro

Wolfram started presenting his camera module use case. He works for Renesas, uses Maxim GMSL chips on an automotive development board with 8 cameras connected on two 4-camera deserializers sharing a unique I2C master from the main SoC.

All serializers and sensors have the same address when powered up, however each of those chips supports reprogramming its slave address. The serdes chipset act as an I2C mux, unfortunately they have all the 4 channels ON by default. This requires a complex reconfiguration phase to avoid address conflicts: each time the cameras are started, all mux ports are closed, then one by one opened and the addresses reprogrammed.

Vitor Soares entered the discussion saying that the I3C bus, unlike I2C, has dynamic address assignment: by default the master assigns a unique slave address dynamically at connection time. I3C also has group addresses. However I3C adoption in current chips seems still very low (“I3C is coming to the real world?”, said Wolfram ironically).

Linus Walleij asked if, even though ugly, a solution could be to reconfigure all the addresses in the bootloader before starting the kernel. It turns out it is not possible because the remote camera modules can be powered on/off at runtime and they lose the address each time.

Luca’s use case

Then Luca presented his use case. The structure is similar, but here the camera modules can be disconnected and reconnected at runtime, potentially with a different model of camera module and while recording from the other camera. This looks like hot-plug.

He uses Texas Instruments FPD-Link III chips, which remap the physical address to an alias instead of being equivalent to an I2C mux. This avoids entirely the need for address reprogramming on the slave chips to avoid address collisions.

Luca previously sent his RFCv2 patches, whose notable design choices include:

  • an I2C adapter is instantiated for each remote I2C bus
  • when a device is added on a remote bus, an alias is chosen for it from a pool
  • the pool of usable aliases is defined in device tree, and must contain addresses known to be unused by physical chips

Tablet use case

Chen-Yu Tsai presented his use case for a tablet product. Key points in this design:

  • There is no serdes involved
  • The SoC is connected to 2 identical cameras, same i2c bus, same address
  • Both cameras are connected on the same MIPI CSI-2 port
  • There is 1 power line per camera, but the reset line is shared

This use case is quite different from the ones discussed. But the select/deselect callbacks could be useful here, said Wolfram.

Laurent Pinchart said having 2 cameras on same MIPI CSI-2 line is a common hardware design.

Address assignment

An important topic is how to select an address to assign to each newly connected remote slave (no matter if it will be changed on the slave itself or it will be remapped to an alias). Wolfram thinks this should be done dynamically.

Wolfram had proposed that all slave addresses not described as used are considered available. He’s not 100% happy with this idea, but he thinks it’s better than listing in device tree a pool of available addresses, as initially proposed by Luca in his patches. After all, device tree should describe what hardware exists, not what does not exist. But this means we’ll need a device tree binding for addresses that are used by a physical device, but whose driver is unknown or not implemented.

Alexandre Belloni asked if this can work also when a chip is defined, because it physically exists, but is disabled in device tree. He has a use case for this, a board with a chip that is installed but whose driver is known to be buggy. Wolfram replied we should fix that in device tree management and still consider the address as used.

Overall, even though the idea of “all-non-described-addresses-are-available” leaves nobody super happy, there was no real objection to it.

Implementation choices

Wolfram said he likes the idea of instantiating an I2C adapter per each remote bus, and he doesn’t understand the downside of not doing it. It makes things clearer, he said.
Jacopo Mondi added that this approach also allows to have different bus speeds on each segment, as the TI chips allow to do.

Wolfram commented on his previous proposal of adding a flag (NEEDS_ATR) to the I2C adapters for remote busses. If this flag is set, when adding a new device the framework would choose an available address, then call a callback on the adapter (the deserializer driver) to apply the binding in the chip.

This would work for the TI chips that use aliases, but for the Maxim chips (looking like a mux) we have to pass the new address to the slave chip driver. Wolfram suggests to augment the i2c_client struct that is passed to the chip probe() function with a field containing the address to be reprogrammed.
Luca observed that in this case the core doesn’t know whether the new i2c_client field has been honored, i.e. whether address reprogramming it is doable by the chip and implemented in the driver. So we probably need a CAN_REPROGRAM_ADDRESS flag in the slave drivers to let the I2C core know.

Niklas Söderlund said this could be achieved with a multi-level approach: when the NEEDS_ATR flag is set the core chooses an address and calls an adapter callback; if the callback doesn’t exist (or returns error) then calls the device callback to set an address.
Jacopo pointed out that the client should be aware at probe time, not later in a callback, or it will be known too late.

Conclusions

A primary goal of the BoF was to let people share their use cases involving I2C address remapping. Since no new relevant use cases emerged, the discussion mostly focused on the possible implementations that had already been discussed on the linux-i2c mailing list. The discussion focused on the details, thus it looks like there is a good consensus on the core of the idea. One less obstacle to proceed to the implementation, apparently.

Booting with U-Boot SPL on ZynqMP, a step forward

A long-standing issue in the ZynqMP users community has been the loading of a PMU firmware configuration object when U-Boot SPL is used. A recent patch to U-Boot addresses the problem at its root.

The “configuration object”

The Platform Management Unit (PMU) needs a configuration object to know how to operate the SoC: which power domains to enable, which peripherals should be accessible by each CPU core, etc.

A configuration object is produced by the Xilinx tools in the form of a C file (pm_cfg_obj.c), which contains values to be passed at runtime to the PMU firmware. It is design-specific, so it has to be regenerated when the design is modified.

The Xilinx workflow: FSBL

When using the workflow supported by Xilinx, the Xilinx FSBL (First Stage Bootloader) has a role similar to the U-Boot SPL: initializing DDR an other low-level setups, then loading ATF and U-Boot proper. FSBL is generated with a built-in configuration object, and passes it to the PMUFW at runtime before jumping to ATF and U-Boot proper.

Xilinx workflow booting: the PMUFW configuration object is loaded by FSBL at runtime

The Community workflow: U-Boot SPL

Many users prefer using U-Boot SPL over the Xilinx FSBL. So far these users had to face a problem: there is no code in U-Boot to load the configuration object in the PMU firmware.

Community workflow booting, so far: the configuration object is hard-coded in the PMUFW

The best workaround for U-Boot SPL users is to apply a patch to the PMUFW itself to have the configuration object built-in and self-load it. This approach works but has drawbacks: among others, it forces to use a different PMUFW binary for each hardware and hardware configuration. It also makes it impossible to change the configuration after boot.

More troubles with meta-xilinx

The mentioned patch has never been included in the meta-xilinx Yocto layer. Many newcomers of ZynqMP have downloaded meta-xilinx, followed its instructions and come up with a non-booting board. They have had a hard time in discovering they need to patch the pmu-firmware in their own layer to be able to boot.

The problem got worse with the Yocto 2.6 (Thud) version of meta-xilinx. In previous versions there was a hack to build a (Microblaze) PMU firmware within an ARM64 build. That hack has been removed from meta-xilinx Thud and replaced with a multiconfig-based setup. Now there are two different configurations: a Microblaze one to build the PMU firmware and an ARM64 one to build all the rest.

This has been a good cleanup, but with an unwanted side-effect: now it is impossible to build two different PMU firmware binaries for two different MACHINEs.

Solving the problem at its root

These increasing difficulties triggered me to try and solve the problem at its very root: the inability of U-Boot SPL to load the configuration object into the PMU firmware at runtime, like the FSBL does.

And it turned out not to be that complex in the end. The communication between the ARM core where SPL runs and the PMU happens via a mailbox. I studied the protocol mostly in the FSBL and ARM Trusted Firmware source code and came up with a simple implementation that is enough for the SPL needs. SPL then uses the mailbox in board_init() to send the configuration object to the PMU firmware.

New Community workflow booting: the PMUFW configuration object is loaded by SPL at runtime

With these changes U-Boot SPL now behaves like FSBL. No need to patch PMU firmware anymore!

With this feature in U-Boot SPL there is no more need for a different PMU firmware binary for each different board configuration. A single PMU firmware binary image can be used to boot any ZynqMP board. Only U-Boot SPL will need to be rebuilt to use a different configuration object. Patching the PMU firmware to hard-code its configuration will not be needed anymore.

Mainlining

I sent a patch with this new feature to the U-Boot mailing list. It took a few iterations to have it in a good shape, and finally the maintainer Michal Simek accepted it at its fifth iterations a few days ago. It should be merged in mainline U-Boot version 2019.10.

Using this new booting process is simple: just set the ZYNQMP_SPL_PM_CFG_OBJ_FILE configuration variable to the location of your configuration object. It will be automatically linked in U-Boot SPL and loaded during board initialization. Leaving the variable empty will leave the old behavior, which can still be used as before.

However note that the configuration object file must be in binary format. The C file produced by the Xilinx tools is not directly usable by U-Boot SPL. In order to convert the file to the proper format I also wrote a tool that automates the process. A patch adding this tool to U-Boot has been accepted together with the first one.

Together these two patches will allow a better booting process for ZynqMP users wanting to use U-Boot SPL, automating the whole building process in their buildsystem from mainline U-Boot and their pm_cfg_obj.c file to bootable images.

Best talks at FOSDEM 2019

FOSDEM 2019 Is over, and it has been awesome once again. A big thank to the FOSDEM volunteers!

Among the talks I attended, Microcontroller Firmware from Scratch by Nikolay Kondrashov was by far the most well made and enjoyable, no matter if I’m not a firmware developer anymore. Nikolay was able to squash a huge amount of precious experience about microcontroller firmware and device drivers writing in his 40 minutes timeslot while making it very easy and fun to understand, thanks to great speaking and perfect supporting slides. I particularly loved the sections about how to find and read chip documentation, understanding hardware schematics, using device registers, interrupt vectors and the stack. I suggest watching the video to firmware newbies for learning and to passionate experts for a refreshing entertainment.

I like talks about about specific classes of hardware and how they are modeled in software, so I loved these talks in the Hardware Enablement and Graphics devrooms:

Finally, a few talks that I liked even though I’m not specifically interested in the topic:

Congratulations to all those speakers, and see you next year!

Building the ZynqMP PMU firmware, the simple way

The PMU firmware

The Zynq UltraScale+ MPSoC, or simply ZynqMP for brevity, is a powerful and complex chip by Xilinx based on ARM cores and an FPGA. Within that chip, the PMU (Platform Management Unit) is a Microblaze processor that handles power states, clock and power domains and other very low-level tasks. It obviously has a crucial role for the chip.

There is no “standard” PMU firmware image: every user is supposed to build a custom one. Luckily its code is open source, and publicly available on the Xilinx Embeddedsw repository.

Building it

Unfortunately building a PMU firmware can be a bit annoying. One of the reasons is that it’s the only programmable Microblaze core in a chip that otherwise has only ARM cores. As such it needs an appropriate toolchain.

One of the solutions is to built it using the Xilinx XSDK, a firmware IDE by Xilinx. But it is a heavyweight tool just to build a 128 kB firmware, and it’s non-trivial to automate in a build process.

The other mainstream option is to let Yocto build it, which is a natural choice if you are using it to build the rest of your system. Some obscure rules are available in the meta-xilinx layer to build a Microblaze toolchain in an otherwise ARM64 configuration, and then use it to build the PMU firmware and its dependencies. This is a powerful method, but it makes it hard to understand how the firmware gets built. It also requires to build a toolchain and several packages at every build from scratch.

Booting with U-Boot SPL

Things get even more complex if you want to boot using U-Boot and its SPL, and here’s why.

To know how the chip resources are to be managed, the PMU firmware needs a “configuration object” to be passed from the outside even before U-Boot proper can start. The Xilinx First Stage Bootloader (FSBL) is able to load the configuration object. But using FSBL has drawbacks, including a poor boot speed.

The obvious alternative is U-Boot SPL, which is fast and the de facto standard in the embedded Linux ecosystem. Except it is currently unable to pass the configuration object to the PMU.

The current best hack to boot with U-Boot SPL is to modify the PMU firmware source code to load a configuration object hard-coded in its own image. This removes the need for the SPL to load it. Implementing this hack requires additional build-time operations, and is implemented for example in the meta-topic Yocto layer. This hack works, although it forces to build a different PMU firmware for every different configuration (e.g. every board), but at the moment there’s not much that can be done. Moreover it adds to the complexity of the build process, since these hacks are not implemented in the meta-xilinx Yocto layer.

Keep it simple, stupid!

Does building a PMU firmware really need to be that complex? Of course not!

So in order to document and simplify the whole process, including the above mentioned hack to boot with U-Boot SPL, I wrote a shell script that does it in the simplest possible way. The design goals for this script are being simple, have minimal dependencies and to be easy to understand and modify.

The resulting script is even simpler than I expected! It also works without the need to setup a Yocto environment or any Xilinx IDE: actually it only needs crosstool-NG to build the Microblaze toolchain and the PMU firmware source code. It also allows to build a toolchain once and reuse it for every build, meaning a different PMU firmware image can be rebuilt in less than 10 seconds.

I published this script on the zynqmp-pmufw-builder GitHub repository. Feel free to use it for your projects, or simply to understand what’s going on when you use other tools!

Embedded Linux Conference Europe 2017

Embedded Linux Conference Europe is the most in-depth technical conference in Europe about Embedded Linux.

For the 2017 edition, taking place in Prague in late October, I will give the talk “How I Survived to a SoC with a Terrible Linux BSP“. It will be a revised edition of the talk I gave last February at FOSDEM 2017.

Among the other talks here are a few ones that caught my attention as particularly interesting:

…and just after that, I’ll be busy for Linux Day 2017 in Bergamo, Italy. I’ll give an introductory talk about “Build Automation with Make, Autotools and CMake”.

FOSDEM 2017

FOSDEM LogoFOSDEM is an exciting event where hackers can meet to share ideas and experiences about free and open source software.

With hundreds of talks in the schedule it’s hard to find a topic that is not covered. And with thousands of participants it’s easy to meet people with common interests, including the developers of free software you’re using daily!

This year I’ve been selected to give talk a titled “How I survived to a SoC with a terrible Linux BSP“.

If you’re interested in embedded Linux systems you’ll probably find interesting talks in the rest of the Embedded, mobile and automotive devroom schedule. But also the Architectures main track, the IoT devroom and the Electronic Design Automation devroom should get a bit of your attention.

See you in Brussels!

Linux Day 2016

Saturday, October 22 will be the Linux Day, an event that brings knowledge about Linux and free software throughout all Italy.

BgLUG sets up a great Linux Day in Bergamo since several years.The event program has recently been released, and once again it is packed with interesting topics.

This year I have been selected to talk about:

  • Data processing on the command line: a short workshop that presents some of the many tools available on the command line and how to combine them to analyze and process data;
  • Objected-oriented programming in C in the Linux kernel: a talk that introduces how to build complex, object oriented software using the C language, showing how these techniques are heavily used in the Linux kernel.

See you there!

Embedded Linux Talk

I created a talk titled Embedded Linux – un pinguino piccolo piccolo (“Embedded Linux – a small small penguin”) to explain the basics of embedded Linux systems to a moderately technical audience.

Here’s the abstract:

An embedded system is a computer, but it doesn’t look like. It can have infinite variants: peripherals, memory, shape… The only rule is that there are no rules! Let’s discover how complex a tiny embedded Linux system is. Then let’s discover how simple it can get bringing an ARM board to life using Buildroot.

Sessions

This talk has been devised for the Linux Day 2015 (see the talk page).

I repeated it in a BgLUG event in March 2016, with an extended live demo, and at the Arduino/Genuino Day 2016, in a shorter form.

Links

You can download the the slides (PDF, italian). The source code is on my GitHub repository.

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close