Practical usage of timer counters in Linux, illustrated on Microchip platforms

Virtually all micro-controllers and micro-processors provide some form of timer counters. In the context of Linux, they are always used for kernel timers, but they can also sometimes be used for PWMs, or input capture devices able to measure external signals such as rotary encoders. In this blog post, we would like to illustrate how Linux can take advantage of such timer counters, by taking the example of the Microchip Timer Counter Block, and depict how its various features fit into existing Linux kernel subsystems.

Hardware overview

On Microchip ARM processors, the TCB (Timer Counter Block) module is a set of three independent, 16 or 32-bits, channels as illustrated in this simplified block diagram:

Microchip TCB

The exact number of TCB modules depends on which Microchip processor you’re using, this Microchip brochure gives the details. Most products have 6 or 9 timer counter channels available, which are grouped into two or three TCB modules, each having 3 channels.

Each TC channel can independently select a clock source for its counter:

  • Internal Clock: sourced from either the system bus clock (often the highest rated one with pre-defined divisors), the slow clock (crystal oscillator) and for the Microchip SAMA5D2 and SAM9X60 SOC series there is even a programmable generic clock source (GCLK) specific to each peripheral.
  • External Clock: based on the three available external input pins: TCLK0, TCLK1 or TCLK2.

The clock source choice should obviously be made depending on the accuracy required by the application.

The module has many functions declined in three different modes:

  • The input capture mode is useful to capture input signals (e.g measure a signal period) through one of the six input pins (TIOAx/TIOBx) connected to each TC module. Each pin can act as trigger source for the counter and two latch register RA/RB can be loaded and compared with a third RC register. This mode is highly configurable with lots of feature to fine tune the capture (subsambling, clock inverting, interrupt, etc.).
  • The waveform mode which provide the core function of TCs as all channels could be used as three independent free-running counters and it is also a mode used to generate PWM signals which gives an extra pool of PWMs
  • The quadrature mode is only supported on the first TC module TCB0 and two (or three) channels are required, channel 0 will decode the speed or position on TIOA0/TIOB0, channel 1 (with TIOB1 input) can be configured to store the revolution or number of rotation. Finally if speed measurement is configured the channel 2 shall define a speed time base.Something important to note is that this mode actually is only part of Microchip SAMA5 and SAM9x60 family SOCs.

Software overview

On the software side in the Linux kernel, the different functionalities offered by the Microchip TCBs will be handled by three different subsystems, which we cover in the following sections.

Clocksource susbsystem

This subsystem is the core target of any TC module as it allows the kernel to keep track of the time passing (clocksource) and program timer interrupts (clockevents). The Microchip TCB has its upstream implementation in drivers/clocksource/timer-atmel-tcb.c that uses the waveform mode to provide both clock source and clock events. The older Microchip platforms have only 16-bit timer counters, in which case two channels are needed to implement the clocksource support. Newer Microchip platforms have 32-bit timer counters, and in this case only one channel is needed to implement clocksource. In both cases, only one channel is necessary to implement clock events.

In the timer-atmel-tcb driver:

  • The clocksource is registered using a struct clocksource structure which mainly provides a ->read() callback to read the current cycle count
  • The clockevents is registered using a struct tc_clkevt_device structure, which provides callbacks to set the date of the next timer event (->set_next_event()) and to change the mode of the timer (->set_state_shutdown(), ->set_state_periodic(), ->set_state_oneshot()).

From a user-space point of view, the clocksource and clockevents subsystems are not directly visible, but they are of course used whenever one uses time or timer related functions. The available clockevents are visible in /sys/bus/clockevents and the available clocksources are visible in /sys/bus/clocksource. The file /proc/timer_list also gives a lot of information about the timers that are pending, and the available timer devices on the platform.

PWM subsystem

This subsystem is useful for many applications (fan control, leds, beepers etc.), and provides both an in-kernel APIs for other kernel drivers to use, as well as a user-space API in /sys/class/pwm, documented at https://www.kernel.org/doc/html/latest/driver-api/pwm.html.

As far as PWM functionality is concerned, the Microchip TCB module is supported by the driver at drivers/pwm/pwm-atmel-tcb.c, which also uses the waveform mode. In this mode both channels pins TIOAx/TIOBx can be used to output PWM signals which allows to provide up to 6 PWM outputs per TCB. On a high-level, this PWM driver registers a struct pwm_ops structure that provides pointers to the important callback to setup and configure PWM outputs.

The current diver implementation has the drawback of using an entire TCB module as a PWM chip: it is not possible to use 1 channel of a TCB module for PWM, and the other channels of the same TCB module for other functionality. On platforms that have only two TCB modules, this means that the first TCB module is typically used for the clockevents/clocksource functionality described previously, and therefore only the second TCB module can be used for PWM.

We are however working on lifting this limitation: Bootlin engineer Alexandre Belloni has a patch series at https://github.com/alexandrebelloni/linux/commits/at91-tcb to address this. We aim at submitting this patch series in the near future.

Thanks to the changes of this patch series, we will be able to use PWM channels as follows:

  • Configuring a 100KHz PWM signal on TIOAx:
    # echo 0 > /sys/class/pwm/pwmchip0/export
    # echo 10000 > /sys/class/pwm/pwmchip0/pwm0/period
    # echo 1000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
    # echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
    
  • Configuring a 100KHz PWM signal on TIOBx:
    # echo 1 > /sys/class/pwm/pwmchip0/export
    # echo 10000 > /sys/class/pwm/pwmchip0/pwm1/period
    # echo 1000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
    # echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable
    
  • One must note that both PWM signals of the same channel will share the same period even though we set it twice here as it is required by the PWM framework. The Microchip TCB takes the period from the RC register and RA/RB respectively for TIOAx/TIOBx duty cycles.

    Counter subsystem

    The Linux kernel counter subsystem, located in drivers/counter/ is much newer than the clocksource, clockevents and PWM subsystems described previously. Indeed, it is only in 2019 that it was added to the Linux kernel, and so far it contains only 5 drivers. This subsystem abstracts a timer counter as three entities: a Count that stores the value incremented or decremented from a measured input Signal and a Synapse that will provide edge-based trigger source.

    This subsystem was therefore very relevant to expose the input capture and quadrature decoder modes of the Microchip TCB module, and we recently submitted a patch series that implements a counter driver for the Microchip TCB module. The driver instantiates and registers a struct counter_device structure, with a variety of sub-structures and callbacks that allow the core counter subsystem to use the Microchip TCB module and expose its input capture and quadrature decoder features to user-space.

    The current user-space interface of the counter subsystem works over sysfs and is documented at https://www.kernel.org/doc/html/latest/driver-api/generic-counter.html. For example, to read the position of a rotary encoder connected to a TCB module configured as a quadradure decoder, one would do:

    # cd /sys/bus/counter/devices/counter0/count0/                    
    # echo "quadrature x4" > function                                 
    # cat count
    0
    

    However, when the device connected to the TCB is a rotary encoder, it would be much more useful to have it exposed to user-space as a standard input device so that all existing graphical libraries and frameworks can automatically make use of it. Rotary encoders connected to GPIOs can already be exposed to user-space as input devices using the rotary_encoder driver. Our goal was to achieve the same, but with a rotary encoder connected to a quadrature decoder handled by the counter subsystem. To this end, we submitted a second patch series, which:

    1. Extends the counter subsystem with an in-kernel API, so that counter devices can not only be used from user-space using sysfs, but also from other kernel subsystems. This is very much like the IIO in-kernel API, which is used in a variety of other kernel subsystems that need access to IIO devices.
    2. A new rotary-encoder-counter driver, which implements an input device based on a counter device configured in quadrature decoder mode.

    Thanks to this driver, we get an input device for our rotary encoder, which can for example be tested using evtest to decode the input events that occur when rotating the rotary encoder:

    # evtest /dev/input/event1                                        
    Input driver version is 1.0.1                                     
    Input device ID: bus 0x19 vendor 0x0 product 0x0 version 0x0      
    Input device name: "rotary@0"                                     
    Supported events:                                                 
    Event type 0 (EV_SYN)                                           
    Event type 2 (EV_REL)                                           
      Event code 0 (REL_X)                                          
    Properties:                                                       
    Testing ... (interrupt to exit)                                   
    Event: time 1325392910.906948, type 2 (EV_REL), code 0 (REL_X), value 2
    Event: time 1325392910.906948, -------------- SYN_REPORT ------------
    Event: time 1325392911.416973, type 2 (EV_REL), code 0 (REL_X), value 1
    Event: time 1325392911.416973, -------------- SYN_REPORT ------------
    Event: time 1325392913.456956, type 2 (EV_REL), code 0 (REL_X), value 2
    Event: time 1325392913.456956, -------------- SYN_REPORT ------------
    Event: time 1325392916.006937, type 2 (EV_REL), code 0 (REL_X), value 1
    Event: time 1325392916.006937, -------------- SYN_REPORT ------------
    Event: time 1325392919.066977, type 2 (EV_REL), code 0 (REL_X), value 1
    Event: time 1325392919.066977, -------------- SYN_REPORT ------------
    Event: time 1325392919.576988, type 2 (EV_REL), code 0 (REL_X), value 2
    Event: time 1325392919.576988, -------------- SYN_REPORT ------------      
    

    Device Tree

    From a Device Tree point of view, the representation is a bit more complicated than for many other hardware blocks, due to the multiple features offered by timer counters. First of all, in the .dtsi file describing the system-on-chip, we have a node that describes each TCB module. For example, for the Microchip SAMA5D2 system-on-chip, which has two TCB modules, we have in arch/arm/boot/dts/sama5d2.dtsi:

    tcb0: timer@f800c000 {
    	compatible = "atmel,at91sam9x5-tcb", "simple-mfd", "syscon";
    	#address-cells = <1>;
    	#size-cells = <0>;
    	reg = <0xf800c000 0x100>;
    	interrupts = <35 IRQ_TYPE_LEVEL_HIGH 0>;
    	clocks = <&pmc PMC_TYPE_PERIPHERAL 35>, <&clk32k>;
    	clock-names = "t0_clk", "slow_clk";
    };
    
    tcb1: timer@f8010000 {
    	compatible = "atmel,at91sam9x5-tcb", "simple-mfd", "syscon";
    	#address-cells = <1>;
    	#size-cells = <0>;
    	reg = <0xf8010000 0x100>;
    	interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>;
    	clocks = <&pmc PMC_TYPE_PERIPHERAL 36>, <&clk32k>;
    	clock-names = "t0_clk", "slow_clk";
    };
    

    This however does not define how each TCB module and each channel is going to be used. This happens at the board level, by adding sub-nodes to the appropriate TCB module node.

    First, each board needs to at least define which TCB module and channels should be used for the clocksource/clockevents. For example, arch/arm/boot/dts/at91-sama5d2_xplained.dts has:

    tcb0: timer@f800c000 {
    	timer0: timer@0 {
    		compatible = "atmel,tcb-timer";
    		reg = <0>;
    	};
    
    	timer1: timer@1 {
    		compatible = "atmel,tcb-timer";
    		reg = <1>;
    	};
    };
    

    As can be seen in this example, the timer@0 and timer@1 node are sub-nodes of the timer@f800c000 node. The SAMA5D2 has 32-bit timer counters, so only one channel is needed for the clocksource, and another channel is needed for clock events. Older platforms such as AT91SAM9260 would need:

    tcb0: timer@fffa0000 {
    	timer@0 {
    		compatible = "atmel,tcb-timer";
    		reg = <0>, <1>;
    	};
    
    	timer@2 {
    		compatible = "atmel,tcb-timer";
    		reg = <2>;
    	};
    };
    

    Where the first instance of atmel,tcb-timer uses two channels: on AT91SAM9260, each channel is only 16-bit, so we need two channels for clocksource. This is why we have reg = <0>, <1> in the first sub-node.

    Now, to use some TCB channels as PWMs, with the new patch series proposed by Alexandre, one would for example use:

    &tcb1 {
    	tcb1_pwm0: pwm@0 {
    		compatible = "atmel,tcb-pwm";
    		#pwm-cells = <3>;
    		reg = <0>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_tcb1_tioa0 &pinctrl_tcb1_tiob0>;
    	};
    
    	tcb1_pwm1: pwm@1 {
    		compatible = "atmel,tcb-pwm";
    		#pwm-cells = <3>;
    		reg = <1>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_tcb1_tioa1>;
    	};
    };
    

    To use the two first channels of TCB1 as PWMs. This would provide two separate PWM devices visible to user-space, and to other kernel drivers.

    Otherwise, to use a TCB as a quadrature decoder, one would use the following piece of Device Tree. Note that we must use the TCB0 module as it is the only one that supports quadrature decoding. This means that the atmel,tcb-timer nodes for clocksource/clockevents support have to use TCB1.

    &tcb0 {
    	qdec: counter@0 {
    		compatible = "atmel,tcb-capture";
    		reg = <0>, <1>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_qdec_default>;
    	};
    };
    

    A quadrature decoder needs two channels, hence the reg = <0>, <1>.

    And if in addition you would like to setup an input device for the rotary encoder connected to the quadrature decoder, you can add:

    rotary@0 {
    	compatible = "rotary-encoder-counter";
    	counter = <&qdec>;
    	qdec-mode = <7>;
    	poll-interval = <50>;
    };
    

    Note that this is not a sub-node of the TCB node, the rotary encoder needs to be described at the top-level of the Device Tree, and has a reference to the TCB channels used as quadrature decoder by means of the counter = <&qdec>; phandle.

    Of course, these different capabilities can be combined. For example, you could use the first two channels of TCB0 to implement a quadrature decoder using the counter subsystem, and the third channel of the same TCB module for a PWM. TCB1 is used for clocksource/clockevents. In this case, the Device Tree would look like this:

    &tcb0 {
    	counter@0 {
    		compatible = "atmel,tcb-capture";
    		reg = <0>, <1>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_qdec_default>;
    	};
    
    	pwm@2 {
    		compatible = "atmel,tcb-pwm";
    		#pwm-cells = <3>;
    		reg = <2>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_tcb1_tioa1>;
    	};
    };
    
    &tcb1 {
    	timer@0 {
    		compatible = "atmel,tcb-timer";
    		reg = <0>, <1>;
    	};
    
    	timer@2 {
    		compatible = "atmel,tcb-timer";
    		reg = <2>;
    	};
    };
    

    Conclusion

    We hope that this blog post was useful to understand how Linux handles timer counters, and what are the Linux kernel subsystems that are involved. Even though we used the Microchip TCB to illustrate our discussion, the concepts all apply to the timer counters of other platforms that would offer similar features.

SFP modules on a board running Linux

We recently worked on Linux support for a custom hardware platform based on the Texas Instruments AM335x system-on-chip, with a somewhat special networking setup: each of the two ports of the AM335x Ethernet MAC was connected to a Microchip VSC8572 Ethernet PHY, which itself allowed to access an SFP cage. In addition, the I2C buses connected to the SFP cages, which are used at runtime to communicate with the inserted SFP modules, instead of being connected to an I2C controller of the system-on-chip as they usually are, where connected to the I2C controller embedded in the VSC8572 PHYs.

The below diagram depicts the overall hardware layout:

Our goal was to use Linux and to offer runtime dynamic reconfiguration of the networking links based the SFP module plugged in. To achieve this we used, and extended, a combination of Linux kernel internal frameworks such as Phylink or the SFP bus support; and of networking device drivers. In this blog post, we’ll share some background information about these technologies, the challenges we faced and our current status.

Introduction to the SFP interface

SFP moduleThe small form-factor pluggable (SFP) is a hot-pluggable network interface module. Its electrical interface and its form-factor are well specified, which allows industry players to build platforms that can host SFP modules, and be sure that they will be able to use any available SFP module on the market. It is commonly used in the networking industry as it allows connecting various types of transceivers to a fixed interface.

A SFP cage provides in addition to data signals a number of control signals:

  • a Tx_Fault pin, for transmitter fault indication
  • a Tx_Disable pin, for disabling optical output
  • a MOD_Abs pin, to detect the absence of a module
  • an Rx_LOS pin, to denote a receiver loss of signal
  • a 2-wire data and clock lines, used to communicate with the modules

Modules plugged into SFP cages can be direct attached cables, in which case they do not have any built-in transceiver, or they can include a transceiver (i.e an embedded PHY), which transforms the signal into another format. This means that in our setup, there can be two PHYs between the Ethernet MAC and the physical medium: the Microchip VSC8572 PHY and the PHY embedded into the SFP module that is plugged in.

All SFP modules embed an EEPROM, accessible at a standardized I2C address and with a standardized format, which allows the host system to discover which SFP modules are connected what are their capabilities. In addition, if the SFP modules contains an embedded PHY, it is also accessible through the same I2C bus.

Challenges

We had to overcome a few challenges to get this setup working, using a mainline Linux kernel.

As we discussed earlier, having SFP modules meant the whole MAC-PHY-SFP link has to be reconfigured at runtime, as the PHY in the SFP module is hot-pluggable. To solve this issue a framework called Phylink, was introduced in mid-2017 to represent networking links and allowing their component to share states and to be reconfigured at runtime. For us, this meant we had to first convert the CPSW MAC driver to use this phylink framework. For a detailed explanation of what composes Ethernet links and why Phylink is needed, we gave a talk at the Embedded Linux Conference Europe in 2018. While we were working on this and after we first moved the CPSW MAC driver to use Phylink, this driver was rewritten and a new CPSW MAC driver was sent upstream (CONFIG_TI_CPSW vs CONFIG_TI_CPSW_SWITCHDEV). We are still using the old driver for now, and this is why we did not send our patches upstream as we think it does not make sense to convert a driver which is now deprecated.

A second challenge was to integrate the 2-wire capability of the VSC8572 PHY into the networking PHY and SFP common code, as our SFP modules I2C bus is connected to the PHY and not an I2C controller from the system-on-chip. We decided to expose this PHY 2-wire capability as an SMBus controller, as the functionality offered by the PHY does not make it a fully I2C compliant controller.

Outcome

The challenges described above made the project quite complex overall, but we were able to get SFP modules working, and to dynamically switch modes depending on the capabilities of the one currently plugged-in. We tested with both direct attached cables and a wide variety of SFP modules of different speeds and functionality. At the moment only a few patches were sent upstream, but we’ll contribute more over time.

For an overview of some of the patches we made and used, we pushed a branch on Github (be aware those patches aren’t upstream yet and they will need some further work to be acceptable upstream). Here is the details of the patches:

In terms of Device Tree representation, we first have a description of the two SFP cages. They describe the different GPIOs used for the control signals, as well as the I2C bus that goes to each SFP cage. Note that the gpio_sfp is a GPIO expander, itself on I2C, rather than directly GPIOs of the system-on-chip.

/ {
       sfp_eth0: sfp-eth0 {
               compatible = "sff,sfp";
               i2c-bus = <&phy0>;
               los-gpios = <&gpio_sfp 3 GPIO_ACTIVE_HIGH>;
               mod-def0-gpios = <&gpio_sfp 4 GPIO_ACTIVE_LOW>;
               tx-disable-gpios = <&gpio_sfp 5 GPIO_ACTIVE_HIGH>;
               tx-fault-gpios = <&gpio_sfp 6 GPIO_ACTIVE_HIGH>;
       };

       sfp_eth1: sfp-eth1 {
               compatible = "sff,sfp";
               i2c-bus = <&phy1>;
               los-gpios = <&gpio_sfp 10 GPIO_ACTIVE_HIGH>;
               mod-def0-gpios = <&gpio_sfp 11 GPIO_ACTIVE_LOW>;
               tx-disable-gpios = <&gpio_sfp 13 GPIO_ACTIVE_HIGH>;
               tx-fault-gpios  = <&gpio_sfp 12 GPIO_ACTIVE_HIGH>;
       };
};

Then the MAC is described as follows:

&mac {
      pinctrl-names = "default";
       pinctrl-0 = <&cpsw_default>;
       status = "okay";
       dual_emac;
};

&cpsw_emac0 {
       status = "okay";
       phy = <&phy0>;
       phy-mode = "rgmii-id";
       dual_emac_res_vlan = <1>;
};

&cpsw_emac1 {
       status = "okay";
       phy = <&phy1>;
       phy-mode = "rgmii-id";
       dual_emac_res_vlan = <2>;
};

So we have both ports of the MAC enabled with a RGMII interface to the PHY. And finally the MDIO bus of the system-on-chip is described as follows. We have two sub-nodes, one for each VSC8572 PHY, respectively at address 0x0 and 0x1 on the CPSW MDIO bus. Each PHY is connected to its respective SFP cage node (sfp_eth0 and sfp_eth1) and provides access to the SFP EEPROM as regular EEPROMs.

&davinci_mdio {
       pinctrl-names = "default";
       pinctrl-0 = <&davinci_mdio_default>;
       status = "okay";

       phy0: ethernet-phy@0 {
               #address-cells = <1>;
               #size-cells = <0>;

               reg = <0>;
               fiber-mode;
               vsc8584,los-active-low;
               sfp = <&sfp_eth0>;

               sfp0_eeprom: eeprom@50 {
                       compatible = "atmel,24c02";
                       reg = <0x50>;
                       read-only;
               };

               sfp0_eeprom_ext: eeprom@51 {
                       compatible = "atmel,24c02";
                       reg = <0x51>;
                       read-only;
               };
       };

       phy1: ethernet-phy@1 {
               #address-cells = <1>;
               #size-cells = <0>;

               reg = <1>;
               fiber-mode;
               vsc8584,los-active-low;
               sfp = <&sfp_eth1>;

               sfp1_eeprom: eeprom@50 {
                       compatible = "atmel,24c02";
                       reg = <0x50>;
                       read-only;
               };

               sfp1_eeprom_ext: eeprom@51 {
                       compatible = "atmel,24c02";
                       reg = <0x51>;
                       read-only;
               };
       };
};

Conclusion

While we are still working on pushing all of this work upstream, we’re happy to have been able to work on these topics. Do not hesitate to reach out of to us if you have projects that involve Linux and SFP modules!

Linux 5.6, Bootlin contributions inside

Linux 5.6 was released last Sunday. As usual, LWN has the best coverage of the new features merged in this release: part 1 and part 2. Sadly, the corresponding KernelNewbies page has not yet been updated with the usual very interesting summary of the important changes.

Bootlin contributed a total of 95 patches to this release, which makes us the 27th contributing company by number of commits, according to the statistics. The main highlights of our contributions are:

  • Our work on supporting hardware-offloading of MACsec encryption/decryption in the networking subsystem and support for this offloading for some Microchip/Vitesse PHYs has been merged. See our previous blog post for more details about this work done by Bootlin engineer Antoine Ténart
  • As part of our work on the Rockchip PX30 system-on-chip, we contributed support for LVDS display on Rockchip PX30, and support for the Satoz SAT050AT40H12R2 panel. This work was done by Miquèl Raynal
  • Alexandre Belloni as the RTC maintainer did his usual number of cleanup and improvements to existing RTC drivers
  • We did a number of small contributions to the Microchip AT91/SAMA5 platform: support for the Smartkiz platform from Overkiz, phylink improvements in the macb driver, etc.
  • Paul Kocialkowski improved the Intel GMA 500 DRM driver to support page flip.
  • Paul Kocialkowski contributed support for the Xylon LogiCVC GPIO controller, which is a preliminary step to contributing the Xylon LogiCVC display controller support. See our blog post on this topic.

In addition to being contributors, a number of Bootlin engineers are also maintainers of various parts of the Linux kernel, and as such:

  • Alexandre Belloni, as the RTC subsystem maintainer and Microchip platforms co-maintainer, has reviewed and merged 55 patches from other contributors
  • Miquèl Raynal, as the MTD co-maintainer, has reviewed and merged 21 patches from other contributors
  • Grégory Clement, as the Marvell EBU platform co-maintainer, has reviewed and merged 12 patches from other contributors

Here is the detail of all our contributions:

Covid-19: Bootlin proposes online sessions for all its courses

Tux working on embedded Linux on a couchLike most of us, due to the Covid-19 epidemic, you may be forced to work from home. To take advantage from this time confined at home, we are now proposing all our training courses as online seminars. You can then benefit from the contents and quality of Bootlin training sessions, without leaving the comfort and safety of your home. During our online seminars, our instructors will alternate between presentations and practical demonstrations, executing the instructions of our practical labs.

At any time, participants will be able to ask questions.

We can propose such remote training both through public online sessions, open to individual registration, as well as dedicated online sessions, for participants from the same company.

Public online sessions

We’re trying to propose time slots that should be manageable from Europe, Middle East, Africa and at least for the East Coast of North America. All such sessions will be taught in English. As usual with all our sessions, all our training materials (lectures and lab instructions) are freely available from the pages describing our courses.

Our Embedded Linux and Linux kernel courses are delivered over 7 half days of 4 hours each, while our Yocto Project, Buildroot and Linux Graphics courses are delivered over 4 half days. For our embedded Linux and Yocto Project courses, we propose an additional date in case some extra time is needed to complete the agenda.

Here are all the available sessions. If the situation lasts longer, we will create new sessions as needed:

Type Dates Time Duration Expected trainer Cost and registration
Embedded Linux (agenda) Sep. 28, 29, 30, Oct. 1, 2, 5, 6 2020. 17:00 – 21:00 (Paris), 8:00 – 12:00 (San Francisco) 28 h Michael Opdenacker 829 EUR + VAT* (register)
Embedded Linux (agenda) Nov. 2, 3, 4, 5, 6, 9, 10, 12, 2020. 14:00 – 18:00 (Paris), 8:00 – 12:00 (New York) 28 h Michael Opdenacker 829 EUR + VAT* (register)
Linux kernel (agenda) Nov. 16, 17, 18, 19, 23, 24, 25, 26 14:00 – 18:00 (Paris time) 28 h Alexandre Belloni 829 EUR + VAT* (register)
Yocto Project (agenda) Nov. 30, Dec. 1, 2, 3, 4, 2020 14:00 – 18:00 (Paris time) 16 h Maxime Chevallier 519 EUR + VAT* (register)
Buildroot (agenda) Dec. 7, 8, 9, 10, and 11, 2020 14:00 – 18:00 (Paris time) 16 h Thomas Petazzoni 519 EUR + VAT* (register)
Linux Graphics (agenda) Dec. 1, 2, 3, 4, 2020 14:00 – 18:00 (Paris time) 16 h Paul Kocialkowski 519 EUR + VAT* (register

* VAT: applies to businesses in France and to individuals from all countries. Businesses in the European Union won’t be charged VAT only if they provide valid company information and VAT number to Evenbrite at registration time. For businesses in other countries, we should be able to grant them a VAT refund, provided they send us a proof of company incorporation before the end of the session.

Each public session will be confirmed once there are at least 6 participants. If the minimum number of participants is not reached, Bootlin will propose new dates or a full refund (including Eventbrite fees) if no new date works for the participant.

We guarantee that the maximum number of participants will be 12.

Dedicated online sessions

If you have enough people to train, such dedicated sessions can be a worthy alternative to public ones:

  • Flexible dates and daily durations, corresponding to the availability of your teams.
  • Confidentiality: freedom to ask questions that are related to your company’s projects and plans.
  • If time left, possibility to have knowledge sharing time with the instructor, that could go beyond the scope of the training course.
  • Language: possibility to have a session in French instead of in English.

Online seminar details

Each session will be given through Jitsi Meet, a Free Software solution that we are trying to promote. As a backup solution, we will also be able to Google Hangouts Meet. Each participant should have her or his own connection and computer (with webcam and microphone) and if possible headsets, to avoid echo issues between audio input and output. This is probably the best solution to allow each participant to ask questions and write comments in the chat window. We also support people connecting from the same conference room with suitable equipment.

Each participant is asked to connect 15 minutes before the session starts, to make sure her or his setup works (instructions will be sent before the event).

How to register

For online public sessions, use the EventBrite links in the above list of sessions to register one or several individuals.

To register an entire group (for dedicated sessions), please contact training@bootlin.com and tell us the type of session you are interested in. We will then send you a registration form to collect all the details we need to send you a quote.

You can also ask all your questions by calling +33 484 258 097.

Questions and answers

Q : Should I order hardware in advance, our hardware included in the training cost?
R : No, practical labs are replaced by technical demonstrations, so you will be able to follow the course without any hardware. However, you can still order the hardware by checking the “Shopping list” pages of presentation materials for each session. This way, between each session, you will be able to replay by yourself the labs demonstrated by your trainer, ask all your questions, and get help between sessions through our dedicated Matrix channel to reach your goals.

Q: Why just demos instead of practicing with real hardware?
A: We are not ready to support a sufficient number of participants doing practical labs remotely with real hardware. This is more complicated and time consuming than in real life. Hence, what we we’re proposing is to replace practical labs with practical demonstrations shown by the instructor. The instructor will go through the normal practical labs with the standard hardware that we’re using.

Q: Would it be possible to run practical labs on the QEMU emulator?
R: Yes, it’s coming. In the embedded Linux course, we are already offering instructions to run most practical labs on QEMU between the sessions, before the practical demos performed by the trainer. We should also be able to propose such instructions for our Yocto Project and Buildroot training courses in the next months. Such work is likely to take more time for our Linux kernel course, practical labs being closer to the hardware that we use.

Q: Why proposing half days instead of full days?
A: From our experience, it’s very difficult to stay focused on a new technical topic for an entire day without having periodic moments when you are active (which happens in our public and on-site sessions, in which we interleave lectures and practical labs). Hence, we believe that daily slots of 4 hours (with a small break in the middle) is a good solution, also leaving extra time for following up your normal work.

Linux 5.5 released, Bootlin contributions inside

Linux 5.5 was recently released, as usual bringing a large number of new features and improvements, which are nicely detailed in the LWN articles on merge window part 1 and merge window part 2, but also on the Kernelnewbies wiki.

According to the statistics, a total of 14350 changes were made to this kernel release, to which Bootlin contributed 124 patches, making us the 19th contributing company by number of commits. Here are the highlights of our contributions:

  • By far and large our most important achievement in Linux 5.5 is the merge of the H265 decoding support in the Allwinner VPU driver, developed by Paul Kocialkowski. This was the last missing feature to complete the effort funded by the Kickstarter campaign we launched in February 2018. See our blog post wrapping up the Allwinner VPU work.
  • Alexandre Belloni as the RTC subsystem maintainer, as usual contributed a large number of RTC driver improvements and fixes.
  • Antoine Ténart contributed some improvements to the Cadence MACB driver, most notably used as the Ethernet controller driver on Microchip/Atmel platforms. The main improvement is the conversion to the phylink subsystem for the interaction with the Ethernet PHY.
  • Grégory Clement contributed numerous enhancements to the Microchip/Atmel SPI controller driver, mainly aimed at fixing and improving the support for Chip Select, both native Chip Selects and GPIO-based Chip Selects.
  • Kamel Bouhara contributed a few additional Device Tree files to describe home automation hardware platforms from Overkiz, based on the Microchip SAMA5D2 processor, as well as an improvement to a Microchip SoC driver that allows to expose the platform serial number to user-space.
  • Miquèl Raynal added support for a new Marvell system-on-chip called Marvell CN9130. Despite the name, this chip is from a hardware point of view in the same family as the Marvell Armada 7K and 8K, which were already supported upstream.
  • Miquèl Raynal contributed a number of fixes and improvements to the Macronix SPI controller driver.
  • Miquèl Raynal added support for the ADC converters over SPI MAX1227, MAX1229 and MAX1231 to the existing max1027 IIO driver in the kernel. These ADCs have a 12-bit resolution.
  • Miquèl Raynal improved the SPI controller driver for the Zynq system-on-chips to correctly support multiple Chip Selects.

In addition to these direct contributions, some of the Bootlin engineers are also Linux kernel maintainers and therefore review and merge patches from other contributors: Alexandre Belloni as the RTC subsystem maintainer and Microchip platform co-maintainer reviewed and merged 45 patches from other contributors, Miquèl Raynal as the MTD subsystem co-maintainer reviewed and merged 39 patches from other contributors and Grégory Clement as the Marvell platform co-maintainer reviewed and merged 29 patches from other contributors.

Here is the detail of our contributions:

Linux 5.4 released, Bootlin contributions inside

LinuxThis time around, we’re quite late to the party, but Linux 5.4 was indeed released a number of weeks ago, and once again, Bootlin contributed a number of patches to this Linux kernel release. As usual, the most useful source of information to learn about the major features brought by Linux 5.4 are the LWN articles (part 1, part 2) and the KernelNewbies Wiki.

With a total of 143 patches contributed to this release, Bootlin is the 17th contributing company by number of commits acccording to the Linux Kernel Patch Statistic.

Here are the highlights of our contributions:

  • Antoine Ténart contributed support for IEEE 1588 Precision Time Protocol (PTP) to the Microsemi Ocelot Ethernet switch driver, which Bootlin developed and upstreamed in 2018 (see our blog post)
  • In the MTD subsystem, a number of contributions to the spi-nor support, written originally by Boris Brezillon, made their way upstream.
  • In the support of Microchip (formerly Atmel) platforms, Kamel Bouhara, who joined Bootlin in September 2019, sees his first kernel contribution merged as a Bootlin engineer: dropping useless support for platform_data from the Atmel PWM driver.
  • In the support of Allwinner platforms
    • Maxime Ripard contributed a brand new driver for the Allwinner A10 camera interface driver, a driver that we started at Bootlin for the CHIP platform back in the days, and that we finished more recently.
    • Maxime Ripard contributed a significant number of improvements to the sun4i-i2s audio interface driver, especially TDM support, which was developed as part of a customer project at Bootlin.
    • Maxime Ripard also contributed numerous enhancements to Allwinner platform Device Tree files, especially in the area of using YAML schemas.
  • In the support for Marvell platforms
    • Grégory Clement added cpufreq support to the Marvell Armada 7K/8K platform by extending some of its clock drivers.
    • Miquèl Raynal contributed improvements to the Marvell CP110 COMPHY driver, which is used to control SERDES lanes on the Marvell Armada 7K/8K platforms, and added the description of the SERDES lanes used by various IP blocks in those processors.
  • Alexandre Belloni, as the RTC subsystem maintainer, did a number of fixes and improvements in several RTC drivers (mainly pcf2123 and pcf8563)
  • For the LPC3250 platform, for which Bootlin delivered a modern BSP to a customer last year, Alexandre Belloni fixed an issue in the lpc_eth network driver, which was preventing the system from booting if the network had been initialized by the bootloader.

In addition to being contributors, some Bootlin engineers are also maintainers of various parts of the Linux kernel, and as such review and merge code from other contributors:

  • As the RTC subsystem maintainer and Microchip platform co-maintainer, Alexandre Belloni merged 47 patches from other contributors
  • As the MTD subsystem co-maintainer, Miquèl Raynal merged 33 patches from other contributors
  • As the Marvell platform co-maintainer, Grégory Clement merged 11 patches from other contributors

Here are the details of all our contributions to Linux 5.4:

Linux 5.3 released, Bootlin contributions inside

Penguin from Mylène Josserand
Drawing from Mylène Josserand, based on a picture from Samuel Blanc (https://commons.wikimedia.org/wiki/File:Manchot_royal_-_King_Penguin.jpg)
The 5.3 version of the Linux kernel was released recently. As usual, we recommend our readers to look at the LWN coverage for this release merge window: part 1 and part 2. Together with the KernelNewbies page, these articles give a very nice overview of the major features and improvements of this new release.

For this release, Bootlin is the 16th contributing company by number of commits, with 143 patches merged in the Linux kernel. Our significant contributions this time were:

  • Support for Allwinner processors
    • The support for H264 video decoding, from Maxime Ripard, was finally merged in the cedrus VPU driver that we have developed thanks to the funding of our Kickstarter campaign last year. The last missing piece is H265 video decoding, which we have submitted several times and we hope to get merged soon.
  • Support for Marvell platforms
    • Antoine Ténart contributed a number of bug fixes and updates to the inside-secure crypto driver, which is used for the cryptographic hardware accelerator found on Marvell Armada 3700 and Marvell Armada 7K/8K.
    • Maxime Chevallier contributed many improvements to the mvpp2 network driver, used on the Marvell Armada 375 and Armada 7K/8K systems. His patches improve the traffic classification offloading capabilities, a topic he will present in detail at the next Embedded Linux Conference Europe.
    • Miquèl Raynal added PHY support for the PCIe Armada 8K driver, and adjusted a few things in the Marvell Armada 7K/8K Device Tree files.
  • Support for Microchip MPU (formerly Atmel) platforms
    • Alexandre Belloni converted the remaining SoCs (SAM9x5, SAM9G45, SAM9RL and SAMA5D3) to the new slow clock controller bindings.
    • Antoine Ténart contributed a few small improvements to the macb driver, for the Cadence network controller used on Microchip platforms.
  • Maxime Ripard contributed numerous YAML Device Tree schemas, to help the effort of converting many Device Tree bindings to the new YAML format, which can be used to validate Device Trees against their bindings.
  • Maxime Ripard contributed numerous patches to the core DRM subsystem: a complete rewrite of the command line parser that parses the DRM-related options of the kernel command line, and support for new options. This was done as part of an effort to make sure the upstream Linux kernel can support all the possible options that the downstream RaspberryPi kernel+firmware combination provides to configure the display.
  • Paul Kocialkowski contributed a few improvements to the RaspberryPi vc4 display controller driver, related to buffer allocation.

Also, several of Bootlin engineers are also kernel maintainers, so they review and merge patches from other contributors:

  • Miquèl Raynal as the NAND subsystem maintainer and MTD subsystem co-maintainer, reviewed and merged 51 patches from other contributors
  • Maxime Ripard as the Allwinner platform co-maintainer, reviewed and merged 38 patches from other contributors
  • Alexandre Belloni as the RTC maintainer and Microchip platform co-maintainer, reviewed and merged 36 patches from other contributors
  • Grégory Clement as the Marvell EBU platform co-maintainer, reviewed and merged 9 patches from other contributors

Here is the details of all our contributions, patch by patch:

Linux 5.0 released, Bootlin contributions

Linux 5.0 was released two weeks ago by Linus Torvalds, and as it is now always the case, Bootlin has contributed a number of patches to this release. For an overview of the new features and improvements brought by Linux 5.0, we as usual recommend to read the LWN articles: merge window summary part 1, merge window summary part 2. The KernelNewbies.org page about this kernel release is also nicely documented.

In terms of contribution to Linux 5.0, according to the LWN statistics, Bootlin is the 12th contributing company by number of commits (261 commits), and 8th contributing company by number of changed lines. Bootlin engineer Maxime Ripard is 11th contributing developer by number of commits, and former Bootlin engineer Boris Brezillon is 12th contributing developer by number of commits, and 8th by number of changed lines. In this release, we are also happy to see numerous contributions from Paul Kocialkoswki who joined Bootlin in November 2018 after his internship working on the Linux kernel support for the Allwinner VPU.

Here are the main highlights of our contributions to Linux 5.0:

  • After 1.5 years of work, the I3C subsystem was finally merged and visible in drivers/i3c in your favorite kernel tree! We are proud to have pioneered the Linux kernel support for this new MIPI standard, which aims at providing an alternate solution to I2C and SPI, with interesting new features (higher speed, device discovery and enumeration, in-band interrupts, and more). See also our initial blog post about I3C, and our blog post about I3C being upstream.
  • In the RTC subsystem, Bootlin engineer and RTC kernel maintainer Alexandre Belloni reworked the way nvmem devices are handled, allowing for multiple nvmem devices to be registered for a single RTC as some have both battery-backed RAM and an on-chip EEPROM. devm_rtc_device_register() has been reimplemented to use the new registration path and is now deprecated. Its counterpart, devm_rtc_device_unregister() has been removed.
  • In the MTD subsystem
    • Boris Brezillon contributed a number of patches to the support for raw NAND mainly related to refactoring the subsystem. For example, some of the patches make the ->select_chip() of nand_chip a legacy hook, and removes its implementation from a number of drivers. All those patches do not bring any new feature per-se, but are part of a larger effort to clean up and modernize the MTD subsystem.
    • Boris Brezillon also contributed to the SPI NOR support a mechanism to fixup the information provided in the BFPT table of SPI NOR flashes. This is used to ensure that some Macronix SPI NOR flashes are properly recognized as supporting 4-byte opcodes.
  • Maxime Ripard contributed a number of improvements to the OV5640 camera sensor driver, especially to remove the hardcoded initialization sequence by a much more flexible initialization code, which allowed to support 60fps and more resolutions.
  • Maxime Ripard extended the PHY subsystem with two new functions, phy_configure() and phy_validate(), which allow to pass configuration details to PHY drivers. This was then used by Maxime to implement MIPI D-PHY drivers, which need a significant number of configuration parameters. See this commit and this commit for details. MIPI D-PHY are typically used in video display or capture HW pipelines.
  • As part of our work on RaspberryPi display support, Boris Brezillon contributed a number of fixs to the VC4 display controller driver.
  • For the support of Microchip MPU (Atmel) platforms, Alexandre Belloni migrated the AT91SAM9260, AT91SAM9261, AT91SAM9263, AT91SAM9RL, AT91SAM9x5, SAMA5D2 and SAMA5D4 platforms to the new clock Device Tree binding that he introduced in Linux 4.20.
  • For the support of Microchip UNG (formerly Microsemi) platforms, Alexandre Belloni added support for the Jaguar2 platform to the pinctrl driver already used for the Ocelot platform.
  • For the support of Allwinnner platforms:
    • Maxime Ripard did a huge amount of Device Tree cleanups and improvements, fixing DTC warnings, but generally making sure those Device Tree files are consistent.
    • Paul Kocialkowski implemented support for YUV planes in the Allwinner display controller driver. This allows to display a video decoded by the VPU directly into a display controller plane, and let the hardware compose it with other display planes, without CPU intervention.
    • Paul Kocialkowski enabled the VPU (for hardware-accelerated video decoding) on the Allwinner H5 and A64. This work was part of our crowdfunding campaign around the Allwinner VPU support.
  • For the support of Marvell platforms
    • Miquèl Raynal added support for suspend/resume to the SATA support on Armada 3720 (the SoC used for the popular EspressoBin platform), as part of a larger effort of bringing full suspend/resume support on Armada 3720
    • Miquèl Raynal implemented support for the thermal overheat interrupt on Armada 7K/8K.

Here is the detailed list of commits we contributed to Linux 5.0:

Free seats in embedded Linux and kernel training sessions (Mar 2019)

Student penguinsAt Bootlin, we owe a lot to the Free Software community, and we’re doing our best to give back as much as we can.

One way of doing that is welcoming community contributors in our public training sessions organized in France. We’ve done that multiple times several years back, and this allowed us to meet very interesting people (who even had very valuable experience and points of view to share with the other course participants), while of course giving them extra knowledge that they can use for further contributions.

Here are the next sessions in which we can offer a free seat:

See our Free training seats page for practical details about how to apply.

Don’t hesitate to apply to this free seat. In past editions, we didn’t have so many people applying, and therefore you have a real chance to get selected!

Allwinner VPU support in mainline Linux end of the year status update

The end of 2018 is approaching, which is the right time to provide an update on where we stand with the Allwinner VPU support in Linux. The promise of our Kickstarter campaign was to deliver all funded stretch goals by the end of 2018. As we’ll explain below, all the goals have been met, and only the upstreaming process is not completely finished for some features.

With the Linux 4.20 release happening just a few days ago, the core of the Cedrus driver and the media Requests API that supports it are finally available through Linus Torvalds’ tree! They provide the required interface for hardware-accelerated MPEG-2 decoding on the A13, A20, A33 and H3 Allwinner SoCs.

Cedrus driver in staging

Discussions regarding the details of the stateless video decoding interface offered by the V4L2 API are still taking place, which explains why our driver was integrated as a staging media driver. It was also decided to hide the associated interface for MPEG-2 decoding from the public kernel headers for now. This way, the interface is not considered stable and can keep evolving as discussions are still taking place. Because the kernel has a policy of never breaking backward compatibility, these interfaces will hardly evolve once they are declared stable, so it is crucial to ensure they are ready when that happens. This is especially true given the level of complexity associated with video decoding and the various pitfalls paving that road.

Status of H264 and H265 decoding support

The code for H264 and H265 decoding is already developed and functional, has already been submitted for upstream inclusion but it hasn’t been merged yet. However, with the decoding interfaces considered unstable for now, it should become easier to bring-in H.264 and H.265 decoding support to mainline. Support for these two codecs in the API and our driver is still under review and we will continue sending new iterations for them, with the suggested changes and fixes as well as adaptations for the still-evolving decoding interface. More specifically, our series need to be updated to the latest proposal for identifying reference frames, which is now based on the timestamps of the buffers.

Platform support: H5, A64 and A10 on the horizon

Regarding the platforms supported by our driver, the patches for H5 and A64 support were accepted since our last update and they will make it to Linux 4.21! We are also looking to send out support for the A10, which was missing from our previous series (but shouldn’t cause any particular trouble).

DRM driver improvements

The adaptations for the DRM driver allowing to display the raw decoded frames from the VPU on older platforms were also finalized, with the first half of the series already queued for 4.21. Subsequent changes in the series are still waiting for more reviews as they affect common parts of the framework.

Conclusion

Overall, we are slowly closing down on this project and hoping to get the remaining pieces of our work integrated in mainline Linux as soon as possible, as there seems to be very few obstacles left in the way.