Kernel Modules from newer kernels

Dear all,

We are currently integrating various ICs which are connected via I2C with the Verdin SoM.
The ICs are being recognized, and we are able to send and read data directly via the userspace APIs (i2ctools).

For some of our ICs there are kernel drivers available, which we would like to use.

I have tried adding custom device tree overlays to load the appropriate kernel drivers for these ICs.
Unfortunately this was unsuccessful. We then figured out that this is because the drivers only exist for newer kernels (5.19 / 6.6), but not for the version in the current Torizon OS release (5.15).

Related to this we have a few questions:

  • How easy is it to essentially “backport” these newer kernel modules to Torizon OS? Are we able to add the source to our own codebase and treat it as a custom kernel module?
  • One driver is only available for the next major kernel revision. If we add the source to our own codebase, will this require further changes to the module?
  • Is it possible to build Torizon OS with a newer kernel? (We are using Torizon Core Builder)
  • How far off (in terms of time) is the official release from using kernel >=6.6? Is there a timeline for the used kernel version?
Technical Details / Versions

SoM-Board: Verdin iMX8M Mini DualLite 1GB Wi-Fi / Bluetooth IT
Carrier Board: Mallow Carrier Board (/ Dhalia Carrier Board)

Torizon OS: 6.7.0+build18 (quaterly release)
Kernel: 5.15.148-6.7.0+git.bfdbfb2c85fb

Drivers needed:
TLA2024, available in 5.19 (part of the ti-ads1015 driver)
MCP4728, available in 6.6

In case someone googles this at some point:
One of our ICs is a TLA2024. The driver for it is part of the TI ADS1015 module. This was the first one we tried to integrate since we knew the driver existed, as it is used for the onboard ADS1015 IC (on the Verdin SoM). However, because of the version difference, the driver inside Torizon OS does not recognize the TLA2024. So if anyone has tried creating a device-tree file for a TLA2024 and wondered why it simply does not load the driver, this is the reason.

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


To address your questions regarding integrating newer kernel drivers with Torizon OS, here are some insights based on the provided context:

  1. Backporting Kernel Modules: Backporting newer kernel modules to an older kernel version like 5.15 can be challenging. It involves adapting the newer module’s code to be compatible with the older kernel’s APIs and infrastructure. You can add the source to your codebase and treat it as a custom kernel module, but this may require significant modifications depending on the changes between kernel versions.

  2. Adding Source to Codebase: If a driver is only available in a newer kernel version, adding its source to your codebase might require additional changes. This is because newer kernel versions might have different APIs or dependencies that are not present in the older kernel version you are using.

  3. Building Torizon OS with a Newer Kernel: The context does not provide specific instructions on building Torizon OS with a newer kernel using TorizonCore Builder. Typically, Torizon OS is provided as a binary distribution, and changing the kernel version would require significant customization and expertise in kernel development.

  4. Timeline for Kernel >=6.6: The context does not provide information on the timeline for when Torizon OS will officially support kernel versions >=6.6. For such information, it would be best to contact Toradex support or check their official release notes and roadmap.

Given these challenges, you might consider reaching out to Toradex support for guidance on backporting specific drivers or inquire about future kernel updates in Torizon OS.

Please, also check if these links can help you solve your problem:

Yocto/Torizon backporting in-tree kernel.

In our project, I have used the torizon-core-builder custom kernel module mechanism for:

  • A camera driver ported over from the raspberry pi kernel. This was a different kernel version (and also lacking some raspberry-pi-specific kernel patches), so it required some changes
  • A image processing driver from the toradex kernel source where I needed some changes (I changed some names and changed the compatible strings so it became essentially a
  • duplicate of the driver that I could activate with the modified compatible string in the devicetree).
  • The gpio watchdog driver that was not enabled in the Toradex kernel (yet, it is now in nightly builds), where I just copied the .c file verbatim and added a Makefile to turn it into a custom module.

The first two of these I published at GitHub - 3devo/FM23-kernel-modules: Linux kernel modules for the FM23 machine, maybe that would be helpful for you.

Very likely, though it also depends a bit on what subsystem the driver is in and how much refactoring of internal interface has been done there.

1 Like

Hi @HTKMBU!

Great timing! :smiley:

The soon-to-be-released Torizon OS 7 will be based on Linux Kernel version 6.6. So this should simply solve your requirements.

It is not yet released, but your can test it already (nightly build): https://artifacts.toradex.com/artifactory/torizoncore-oe-prerelease-frankfurt/scarthgap-7.x.y/nightly/68/verdin-imx8mm/torizon/torizon-docker-evaluation/oedeploy/torizon-docker-evaluation-verdin-imx8mm-Tezi_7.0.0-devel-20241009%2Bbuild.68.container.tar.

From what I could check, seems like MCP4728 is not enabled (CONFIG_MCP4728) and TLA2024 (CONFIG_TI_ADS1015) is enabled as a kernel module.

If you want, I can trigger the process to enable MCP4728 on Torizon OS, so (if there is no issue), you will get it on Torizon OS by default after the process is concluded. Would you like me to trigger the process?

Best regards,

@matthijs Thank you for your insights, fortunately it seems we don’t have to implement it ourselves, but it is helpful to know it is possible.

@henrique.tx This sounds great if we can go forward with the new version.
I’ll test it tomorrow to see if there are any issues with our existing codebase, but I don’t expect any since we don’t do any special modifications.

I don’t know what the process entails, if it is not a lot of work I would love if you can trigger it already.
Alternatively if you’d like to wait until we’ve checked the TLA2024, I’ll do that tomorrow and report back.

Hi @HTKMBU !

We could indeed trigger it.

But I agree with you here. I think it is better if you could get the image and “have a look”.

We will be waiting for your feedback :slight_smile:

Have a nice day!

Best regards,

Good news, I have loaded the new firmware and applied our device tree overlay (with the TLA2024), and everything seems to work.
The driver is being loaded and runs as expected.

I’ve also tested our existing code and we can run it on the new firmware with no (code) changes.
(This does not include any access to the TLA2024, but does include ethernet and userspace i2c interaction)
For some reason the log directory did not exist. (“/var/log” is a symlink pointing to “/var/volatile/log”, which did not exist. After creating the directory, our code works as expected.)
@henrique.tx Do you know if this this changed in 7.0? Or is this just a weirdness with the update process? I know we have to change it to make it persistent, but I think the general log directory itself existed in 6.x by default.

@henrique.tx Could you trigger the process to add the MCP4728? If you need us to test anything we’re happy to do so as well.

If anyone ever finds this useful, here is the device tree file for the TLA2024 (change address as needed)

Device Tree file for TLA2024
// Definitions for TLS2024 @ 0x4b
/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,verdin-imx8mm";
};

// /dev/verdin-i2c1
&i2c4 {
    #address-cells = <1>;
    #size-cells = <0>;
    clock-frequency = <400000>;
    status = "okay";
    
    // TLA2024 @ verdin-i2c1 0x4b
    // https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/ti%2Cads1015.yaml
    adc@4b {
        compatible = "ti,tla2024";
        reg = <0x4b>;
        #address-cells = <1>;
        #size-cells = <0>;
        
        /* Verdin I2C_1 (ADC_4 - ADC_3) */
        channel@0 {
            reg = <0>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 (ADC_4 - ADC_1) */
        channel@1 {
            reg = <1>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 (ADC_3 - ADC_1) */
        channel@2 {
            reg = <2>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 (ADC_2 - ADC_1) */
        channel@3 {
            reg = <3>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 ADC_4 */
        channel@4 {
            reg = <4>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 ADC_3 */
        channel@5 {
            reg = <5>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 ADC_2 */
        channel@6 {
            reg = <6>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };

        /* Verdin I2C_1 ADC_1 */
        channel@7 {
            reg = <7>;
            ti,gain = <2>;
            ti,datarate = <4>;
        };
    };

};

Hi @HTKMBU !

I just checked Torizon OS 7.0.0 against Torizon OS 6.7.0:

Torizon OS 6.7.0

torizon@verdin-imx8mp-15247228:~$ sudo tdx-info | grep version
Kernel version:           5.15.148-6.7.0+git.bfdbfb2c85fb #1-TorizonCore SMP PREEMPT Thu Jun 20 15:59:41 UTC 2024
Distro version:           VERSION_ID=6.7.0-build.18
Toradex version:          0058 V1.1A
torizon@verdin-imx8mp-15247228:~$ ls -la /var/ | grep log
lrwxrwxrwx  1 root root   17 Apr 28  2022 log -> /var/volatile/log
torizon@verdin-imx8mp-15247228:~$

Torizon OS 7.0.0

torizon@verdin-am62-15133487:~$ sudo tdx-info | grep version
Kernel version:           6.6.32-7.0.0-g803472c67051 #1-Torizon SMP PREEMPT Fri Sep 27 07:55:54 UTC 2024
Distro version:           VERSION_ID=7.0.0-build.1
^[[AToradex version:          0076 V1.1A
torizon@verdin-am62-15133487:~$ ls -la /var/ | grep log
lrwxrwxrwx  1 root root   17 Feb 27  2024 log -> /var/volatile/log

As we can see, on both versions /var/log is a symlink to /var/volatile/log on both cases. I would like to ask you to double check this on your side, if possible :slight_smile:


Sure!

I will trigger the process.

Best regards,

Hi @HTKMBU !

Sorry for the delay here.

The kernel config for MCP4728 is already available on the latest night build of Torizon OS (7.1.0-devel-something).

For reference, this is the ticket TOR-3615: https://developer-archives.toradex.com/software/torizon/release-details?view=all&key=TOR-3615

It is available for download on Index of torizoncore-oe-prerelease-frankfurt/scarthgap-7.x.y/nightly/80/verdin-imx8mm/torizon/torizon-docker-evaluation/oedeploy

Please let us know how it goes :slight_smile:

Best regards,

Hi @henrique.tx,

Same about the delay from my side, this fell out of the last sprint, so I only have time now.

I have tested the nightly (and monthly) build from 7.1.0, and the driver and configuration is working.

Specifics:

Tested versions

7.1.0 Nightly Build 96 (2024-11-13)
7.1.0 Monthly Build 2 (2024-11)

Device Tree Overlay
/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,verdin-imx8mm";
};

// /dev/verdin-i2c1
&i2c4 {
    #address-cells = <1>;
    #size-cells = <0>;
    clock-frequency = <400000>;
    status = "okay";

    // MCP4728 @ verdin-i2c1 0x60
    dac@60 {
        compatible = "microchip,mcp4728";
        reg = <0x60>;
        vdd-supply = <&reg_5p0v>;
    };

    // MCP4728 @ verdin-i2c1 0x61
    dac@61 {
        compatible = "microchip,mcp4728";
        reg = <0x61>;
        vdd-supply = <&reg_5p0v>;
    };
};

One thing which was not obvious for me was what to set the vdd-supply parameter to. I have now set it to a 5V Regulator from the base device tree, but am not sure if this is even right. I’m assuming it is used to determine the scale / voltage conversion, but am very unsure about it. (And I also can’t find any documentation about it anywhere).
If anyone knows anything about how this works I would be very glad to hear. (Or if you know where this is documented).

Some more things to note if anyone else wants to use the MCP4728:

  • By default the driver uses the internal voltage reference for the output, meaning it only puts out 4.096V at most (2 * VRef). To set it to VDD output, you need to set the scale parameter by setting the out_voltageX_scale in sysfs to the appropriate value from the out_voltage_scale_available file. (For us, this was 1.220703 for 0 - 5V. For 1 * VRef mode it is 0.5)
  • The output is set in the out_voltageX_raw, and is in increments between 0 and 4095 (12 bit resolution from the DAC Chip). To get real values you then multiply with the out_voltageX_scale and then have the mV for the output.

In any case, thank you for adding the driver to the firmware! From our side everything we needed is working now.

Hi @HTKMBU !

Thanks for the feedback and for the extra notes about your work to use it.

I am sure this will be helpful for the others using the same device :smiley:

Such regulators are available and can/must be used on some device tree nodes to fulfill their vdd-supply-like needs. On the other hand, some regulators are managed and you have some GPIO that allow you to turn them on/off. It makes sense to use a regulator that represents correctly the VDD of the device. If it is 5V in your case, so you are good to good.

Also, if this thread is solved, please do not forget to check the suitable message here as the solution :wink:

Best regards,