Modify the Linux devicetree#

Ensure that the Linux devicetree will not request the remote core’s peripheral.

We want to run the GPIO Input Interrupt example on a remote core. Let’s check the Linux devicetree file to make sure that both the MCU GPIO module, and the interrupt controller for the MCU GPIO module, are disabled in Linux.

Look for all references to the peripheral#

First, let’s search for every Linux devicetree file that mentions the peripheral.

Let’s say we are running tests on the AM62Px SK EVM. The Linux devicetree file for that board is in the Linux SDK at board-support/ti-linux-kernel/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts.

This is the board devicetree file. Most changes to the Linux devicetree should be made to the board devicetree file.

The board devicetree file includes other .dtsi files that define the components of the processor. For example, the parts of the AM62Px that are in the MAIN domain are defined in k3-am62p-main.dtsi. The parts of the AM62Px that are in the MCU domain are defined in k3-am62p-mcu.dtsi.

ti-linux-kernel/arch/arm64/boot/dts/ti$ grep -r --include=k3-am62* mcu_gpio
k3-am62-mcu.dtsi:       mcu_gpio_intr: interrupt-controller@4210000 {
k3-am62-mcu.dtsi:       mcu_gpio0: gpio@4201000 {
k3-am62-mcu.dtsi:               interrupt-parent = <&mcu_gpio_intr>;
k3-am625-beagleplay.dts:                gpio2 = &mcu_gpio0;
k3-am62x-sk-common.dtsi:/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
k3-am62x-sk-common.dtsi:&mcu_gpio0 {
k3-am62x-sk-common.dtsi:&mcu_gpio_intr {
k3-am62x-sk-lpm-wkup-sources.dtso:      mcu_gpio_key {
k3-am62x-sk-lpm-wkup-sources.dtso:              interrupt-parent = <&mcu_gpio0>;
k3-am62x-sk-lpm-wkup-sources.dtso:                      gpios = <&mcu_gpio0 4 GPIO_ACTIVE_LOW>;
k3-am62x-sk-lpm-wkup-sources.dtso:&mcu_gpio0 {
k3-am62x-sk-lpm-wkup-sources.dtso:&mcu_gpio_intr {
k3-am62a7-sk.dts:&mcu_gpio0 {
k3-am62a7-sk.dts:               interrupt-parent = <&mcu_gpio0>;
k3-am62p-mcu.dtsi:      mcu_gpio_intr: interrupt-controller@4210000 {
k3-am62p-mcu.dtsi:      mcu_gpio0: gpio@4201000 {
k3-am62p-mcu.dtsi:              interrupt-parent = <&mcu_gpio_intr>;
k3-am62p5-sk.dts:/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
k3-am62p5-sk.dts:&mcu_gpio0 {
k3-am62p5-sk.dts:&mcu_gpio_intr {
k3-am62a-mcu.dtsi:      mcu_gpio_intr: interrupt-controller@4210000 {
k3-am62a-mcu.dtsi:      mcu_gpio0: gpio@4201000 {
k3-am62a-mcu.dtsi:              interrupt-parent = <&mcu_gpio_intr>;

Determine whether the peripheral is enabled or disabled#

Remember, if a Linux devicetree node is defined, then it is enabled by default. That means that the next step is to read through every file that shows up to see whether the peripheral has been disabled.

Device tree basics#

We cannot provide a full training on Linux device tree here. However, there are plenty of resources online, such as Bootlin’s excellent device tree trainings.

In general, device tree files can be divided into:

  • processor DTSI files

  • board-level DTS files

Processor DTSI files#

Processor DTSI files contain node definitions. These DTSI files describe the SOC itself, as well as all the peripherals within the selected processor. The DTSI files are used as include files for a custom board DTS file.

Typically these DTSI files are used as-is and should NOT be edited! DTSI file settings can be overwritten by whichever DTS file includes them, so all custom DTS settings can be placed in the custom board DTS file.

Board-level DTS files#

Changes should be made to board-level .dts files instead of the processor .dtsi files. You build the device tree binary file (.dtb) file from a specific .dts file.

How are Linux device tree settings applied?#

At a conceptual level, you build a .dtb file from a specific .dts file. During the compilation process, any #include files are inserted by the compiler in the EXACT line where the #include directive is. Once all #include files have been added to the .dts file, the compiler reads the single document from top to bottom, and applies settings in the order that it reads the settings. If one specific setting is modified in multiple places, then the last setting is the one that is applied.

Let’s pretend we wanted to use k3-am625-sk.dts:

k3-am625-sk.dts
---------------

#include "k3-am62x-sk-common.dtsi"

/* k3-am625-sk.dts contents here */
enable peripheralX
k3-am62x-sk-common.dtsi
-----------------------

#include "k3-am625.dtsi"

/* k3-am62x-sk-common.dtsi contents here */
disable peripheralX
k3-am625.dtsi
-------------

#include "k3-am62.dtsi"

/* k3-am625.dtsi contents here */
k3-am62.dtsi
------------

/* k3-am62.dtsi contents here */

/* Now include the peripherals for each bus segments */
#include "k3-am62-main.dtsi"
#include "k3-am62-mcu.dtsi"
#include "k3-am62-wakeup.dtsi"
k3-am62-mcu.dtsi
----------------

/* k3-am62-mcu.dtsi contents here */
define peripheralX (peripheralX enabled)

Will peripheralX be enabled or disabled? Let’s combine the files to see what the compiler would do. I will use brackets to help keep track of which include file is being read on each line:

k3-am625-sk.dts
---------------

#include "k3-am62x-sk-common.dtsi"{

    #include "k3-am625.dtsi"{

        #include "k3-am62.dtsi"{

            /* k3-am62.dtsi contents here */

            /* Now include the peripherals for each bus segments */
            #include "k3-am62-main.dtsi"
            #include "k3-am62-mcu.dtsi"{

                /* k3-am62-mcu.dtsi contents here */
                define peripheralX (i.e., peripheralX enabled)
            }
            #include "k3-am62-wakeup.dtsi"

        }

        /* k3-am625.dtsi contents here */
    }

    /* k3-am62x-sk-common.dtsi contents here */
    disable peripheralX
}

/* k3-am625-sk.dts contents here */
enable peripheralX

If we’re reading the k3-am625-sk.dts file from top to bottom, we’ll see that peripheralX is enabled, since the last time the status was set is in k3-am625-sk.dts.

Note

This example demonstrates why changes to the Linux devicetree file should be made in the top-level board devicetree file instead of the included .dtsi files.

Settings made in a .dtsi file can be overwritten by .dts files that include the .dtsi file. That means that changes to a .dtsi file may be overwritten by another file.

However, if the top-level board .dts file is not included by any other .dts files, you can guarantee that your changes to the board .dts file will NOT be overwritten.

TI occasionally updates .dtsi files in new SDK releases. Leaving the low level .dtsi files untouched allows for easier board porting in the future.

Is mcu_gpio0 enabled or disabled by default?#

Note

What is the difference between marking a devicetree node as “disabled”, or “reserved”?

These statuses in the device tree accomplish the same thing, so use whichever you want. Either way, Linux will not try to turn on clocks for the node, and Linux will not try to access the node during runtime.

Both the MCU GPIO module and the MCU GPIO interrupt controller are reserved in k3-am62p5-sk.dts. If you are using the SK EVM, then Linux will not try to use the MCU GPIO module:

/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
&mcu_gpio0 {
       status = "reserved";
};

&mcu_gpio_intr {
        status = "reserved";
};

For demonstration purposes, let’s also take a look at the AM62x:

mcu_gpio0 & mcu_gpio_intr are defined (and thus enabled) in k3-am62-mcu.dtsi.

Both the MCU GPIO module and the MCU GPIO interrupt controller are reserved in k3-am62x-sk-common.dtsi, so Linux will not try to use the MCU GPIO module if you are using any SK EVMs.

/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
&mcu_gpio0 {
        status = "reserved";
};

&mcu_gpio_intr {
        status = "reserved";
};

But what if you were using a different AM62x board?

k3-am625-beagleplay.dts does NOT disable the nodes, so they are still enabled.

And overlay file k3-am62x-sk-lpm-wkup-sources.dtso actively enables and uses the nodes. If either of these devicetree files were used, Linux would attempt to claim the mcu_gpio0 peripheral.

Disable the peripheral (if needed)#

Once you make changes to the Linux devicetree, build the devicetree as documented in the Linux SDK Kernel User’s Guide.

Before building the device tree binary, you DO need to export the compiler and apply the kernel configuration as documented in the Kernel User’s Guide. However, it is not required to rebuild the kernel and the kernel modules before running the MCU+ SDK GPIO Interrupt example - you only need to build the new devicetree file.

The new devicetree file must be copied into the /boot directory of the EVM’s Linux filesystem. For ideas about how to copy files into the Linux filesystem, refer to How to copy a file onto the Linux filesystem.