> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Device tree architecture

The Qualcomm<sup>®</sup> Linux kernel uses a layered device tree (DT) architecture where
platform-specific hardware description is separated from SoC-level configuration.
At boot, UEFI firmware selects the correct DTB from a FIT image by matching
hardware-detected identifiers against `compatible` strings.

## DTS and DTSI file structure

Device tree source files are located under `arch/arm64/boot/dts/qcom/` in the
kernel source tree.

**Table: Device tree file types**

| File type | Purpose |
| - | - |
| `.dtsi` | SoC-level or shared hardware description. Included by board DTS files. |
| `.dts` | Board-level file. Includes one or more DTSI files and adds board-specific nodes such as pinmux settings, regulators, and on-board peripherals. |
| `.dtb` | Compiled binary output from a DTS file. Loaded by the bootloader at runtime. |
| `.dtbo` | Device tree overlay binary. Applied on top of a base DTB to enable optional hardware configurations such as mezzanine boards. |

## Board vs SoC layering

Qualcomm Linux follows a strict two-tier layering convention:

1. **SoC DTSI** (for example, `qcs6490.dtsi`), defines clocks, power domains,
   interrupt controllers, and core peripherals that are common to all boards
   using that SoC.

2. **Board DTS** (for example, `qcs6490-rb3gen2.dts`), includes the SoC DTSI
   and adds board-specific nodes: GPIO assignments, regulator values, on-board
   sensors, and display panels.

A typical board DTS begins with:

```dts theme={null}
#include <dt-bindings/...>
#include "qcs6490.dtsi"

/ {
    model = "Qualcomm QCS6490 Dragonwing™ RB3 Gen2";
    compatible = "qcom,qcs6490-rb3gen2", "qcom,qcs6490";
    /* ... additional board-specific nodes ... */
};
```

## FIT-based DTB packaging

Qualcomm Linux supports multiple SoCs and boards within a single software
release. DTBs are packaged into one Flattened Image Tree (FIT) image
(`qclinux_fit.img`) stored in the `dtb_a` partition. UEFI firmware selects
the correct DTB at boot by matching hardware-detected identifiers against the
`compatible` string of each FIT configuration entry.

The FIT image is described by an Image Tree Source (`.its`) file and built
with `mkimage`. It has two top-level sections:

* `images`, declares every binary blob: DTBs, DTBOs, and the metadata binary.
* `configurations`, declares every platform configuration, each referencing
  one or more images.

A minimal ITS skeleton:

```text theme={null}
/dts-v1/;
/ {
    images {
        /* metadata maps config compatible strings to hardware IDs */
        fdt-qcom-metadata.dtb {
            data = /incbin/("./qcom-metadata.dtb");
            type = "qcom_metadata";
        };
        fdt-<soc>-<board>.dtb {
            data = /incbin/("./arch/arm64/boot/dts/qcom/<soc>-<board>.dtb");
            type = "flat_dt";
        };
    };
    configurations {
        conf-1 {
            compatible = "qcom,<soc>-<board>";
            fdt = "fdt-<soc>-<board>.dtb";
        };
        /* Base DTB + software overlay (CamX) + hardware overlay */
        conf-2 {
            compatible = "qcom,qcs9075-iot-camx-el2kvm";
            fdt = "fdt-lemans-evk.dtb",
                  "fdt-lemans-evk-camx.dtbo",
                  "fdt-lemans-el2.dtbo";
        };
    };
};
```

### Qualcomm DTB metadata

The [qcom-dtb-metadata](https://github.com/qualcomm-linux/qcom-dtb-metadata)
project provides:

* `qcom-metadata.dts` compiles into a metadata DTB used by firmware to map
  hardware identifiers to FIT configuration `compatible` strings.
* `qcom-next-fitimage.its` is the ITS template for standalone builds.

The metadata DTS groups allowable `compatible` string suffix tokens into nodes:
`soc`, `soc-sku`, `socver`, `board`, `boardrev`, `board-subtype-*`, `softsku`,
and `oem`.

### Boot-time DTB selection flow

1. UEFI loads `qclinux_fit.img` from the `dtb_a` partition.
2. The embedded `qcom-metadata.dtb` is parsed to build a table mapping hardware
   numeric IDs to symbolic token names used in `compatible` strings.
3. Hardware identifiers are read: SoC chip ID/version, board type and revision
   from the Configuration Data Table (CDT), storage type, and DDR size.
4. FIT configurations are iterated in order (`conf-1`, `conf-2`, …).
5. For each configuration, every token in its `compatible` string is matched
   exactly against hardware-derived values. The first configuration where all
   tokens match is selected.
6. The selected configuration's DTB(s) are loaded and passed to the OS via
   EFI boot.
7. If no configuration matches, boot fails. See
   [Common DT issues & fixes](./common-dt-issues#no-dtb-loaded-due-to-fit-configuration-match-failure)
   for diagnosis steps.

### Compatible string format

Each FIT configuration's `compatible` string encodes platform identity as
dash-separated tokens:

```text theme={null}
qcom,<soc>[-<soc-sku>][-<socver>]-<board>[-<boardrev>]
          [-<peripheral-subtype>][-<storage-type>][-<memory-size>]
          [-<softsku>][-<oem>]
```

Omitting a token leaves that dimension unconstrained, i.e. it matches any hardware
value for that field. More specific strings should appear before generic ones
in the `configurations` block.

**Examples:**

```text theme={null}
qcom,qcm6490-idp                 # SoC + board only (matches all revisions)
qcom,qcs9100-qam-r1.0            # SoC + board + explicit board revision
qcom,qcs6490-iot-subtype2        # SoC + board + peripheral subtype
```

## Wire DTBs into the FIT image (Yocto)

The Yocto build generates the FIT image from two inputs:

* `KERNEL_DEVICETREE` and `LINUX_QCOM_KERNEL_DEVICETREE` represent the list of DTBs
  and DTBOs to package into the `images` section.
* `FIT_DTB_COMPATIBLE` entries in
  `conf/machine/include/fit-dtb-compatible.inc` enumerates the `configurations` section
  entries that map a DTB (or DTB+DTBO combination) to the hardware
  `compatible` strings UEFI will match at boot.

```text theme={null}
# Upstream DTBs and DTBOs
KERNEL_DEVICETREE ?= " \
    qcom/qcs6490-rb3gen2.dtb \
    qcom/qcs6490-rb3gen2-industrial-mezzanine.dtbo \
    qcom/qcs6490-rb3gen2-vision-mezzanine.dtbo \
    "

# Downstream-only DTBOs (not yet upstreamed)
LINUX_QCOM_KERNEL_DEVICETREE ?= " \
    qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtbo \
    "
```

### FIT\_DTB\_COMPATIBLE entries

Each entry maps a DTB key (or `DTB+DTBO` key, using `+` as a separator) to one
or more `compatible` strings:

**Single DTB with no overlay:**

```text theme={null}
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2] = " \
    qcom,qcs5430-iot \
    qcom,qcs6490-iot \
    "
```

**DTB + DTBO combination:**

```text theme={null}
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine] = " \
    qcom,qcs5430-iot-subtype2 \
    qcom,qcs6490-iot-subtype2 \
    "
```

**Multiple combinations for the same base DTB:**

```text theme={null}
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2] = " \
    qcom,qcs5430-iot \
    qcom,qcs6490-iot \
    "
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-industrial-mezzanine] = " \
    qcom,qcs5430-iot-subtype9 \
    qcom,qcs6490-iot-subtype9 \
    "
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine] = " \
    qcom,qcs5430-iot-subtype2 \
    qcom,qcs6490-iot-subtype2 \
    "
FIT_DTB_COMPATIBLE[qcs6490-rb3gen2+qcs6490-rb3gen2-vision-mezzanine-camx] = " \
    qcom,qcs6490-iot-camx \
    qcom,qcs6490-iot-subtype2-camx \
    "
```

These entries produce a `configurations` block in the FIT image where each
`conf-N` entry carries the corresponding `compatible` string and `fdt` list.
UEFI iterates these in order and selects the first matching configuration.

<Note>
  More specific `compatible` strings must appear before generic ones in the
  `configurations` block. FIT evaluates configurations in order; the first
  match wins. See [Device tree architecture](./device-tree-architecture#compatible-string-format)
  for the compatible string token reference.
</Note>

## Apply a device tree overlay at runtime

Qualcomm Linux applies device tree overlays during boot rather than while Linux is running. UEFI reads the `VendorDtbOverlays` EFI variable, selects the matching overlay set from `dtb.bin`, and merges it into the device tree before passing control to the kernel. As a result, the system applies any changes to the variable on the next boot.

<Note>
  The mainline kernel has no user-space interface for applying an overlay to the
  live device tree. It exposes `of_overlay_fdt_apply()` only as an in-kernel API, and
  Qualcomm Linux doesn't enable a configfs- or sysfs-based overlay loader. Therefore, you can't use procedures that write a `.dtbo` file to a sysfs or configfs node on this platform. For information about the in-kernel API, see:
  [Devicetree Overlay Notes](https://docs.kernel.org/devicetree/overlay-notes.html).
</Note>

### Select an overlay set

The `VendorDtbOverlays` EFI variable accepts the following values:

**Table: VendorDtbOverlays values**

| Value | Effect |
| - | - |
| `el2kvm` | Applies the `*-el2.dtso` overlays so Linux runs at EL2 as a KVM host. |
| `staging` | Applies the `*-staging.dtso` overlays that enable in-tree drivers not yet upstream. |
| `camx` | Applies the `*-camx.dtso` overlays that replace upstream `camss` with the CAMX camera stack. |

Use the following procedure to apply an overlay set:

1. Confirm `efivarfs` is mounted so the variable is writable:

   ```bash theme={null}
   mount | grep efivarfs
   # If not mounted:
   mount -t efivarfs efivarfs /sys/firmware/efi/efivars
   ```

2. Write the overlay name to the variable. Replace `<overlay>` with a value from
   the preceding table:

   ```bash theme={null}
   echo -n "<overlay>" > /tmp/overlay
   efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays \
       -w -f /tmp/overlay
   ```

3. Read the variable back to confirm it was written:

   ```bash theme={null}
   efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -p
   ```

4. Flush the write to storage and reboot. The variable lives in the RPMB-backed
   EFI variable store, so an unflushed write is lost on reset:

   ```bash theme={null}
   sync && reboot
   ```

5. After the device boots, confirm UEFI read and applied the overlay. The
   following lines appear on the UEFI serial console:

   ```text theme={null}
   Variable VendorDtbOverlays read successfully. Data: camx
   ProcessQcomRuntimeOverlayRequest: Parsed camx
   ```

6. Confirm that the overlay reached the kernel by checking for a node that the overlay adds:

   ```bash theme={null}
   # Example: the CAMX overlay disables the upstream camss node
   cat /proc/device-tree/soc@0/camss@ac5a000/status
   # Compare the full tree against the pre-overlay state
   dtc -I fs -O dts /proc/device-tree 2>/dev/null > /tmp/live.dts
   ```

### Combine overlay sets

To apply more than one overlay set, separate the values with a comma:

```bash theme={null}
echo -n "camx,el2kvm" > /tmp/overlay
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays \
    -w -f /tmp/overlay
sync && reboot
```

### Revert to the default device tree

Delete the variable and reboot the system. UEFI then skips overlay application and boots the base platform DTB:

```bash theme={null}
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -d
sync && reboot
```

## EL2 device trees for KVM

Device tree files marked with `el2` in the filename support Linux running at
Exception Level 2 (EL2) for KVM. The build system applies `el2` overlays to
the platform DTB to generate EL2 DTB variants. Targets by default boot into KVM
mode, except few targets that may not be KVM ready yet. Please refer release
notes to know about platform capability. See [Enable virtualization](./enable-virtualization)
for more details.

## Staging device tree overlays

Device tree files marked with `staging` in the filename enable in-kernel-tree
drivers that are present in the kernel source but not yet submitted upstream.
Examples include SoC-level TGU nodes (`kodiak-staging.dtso`,
`lemans-staging.dtso`, `monaco-staging.dtso`, `talos-staging.dtso`) and
board-level staging Ethernet PHY overlays for development kits. The build
system applies these overlays when the `VendorDtbOverlays` EFI variable is set
to `staging`:

```bash theme={null}
echo -n "staging" > /tmp/overlay
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays \
    -w -f /tmp/overlay
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -p
sync && reboot
```

<Note>
  Use staging DTBs when staging downstream features are required.
</Note>

## CAMX camera device tree overlays

Device tree files marked with `camx` in the filename replace the upstream
camera subsystem (`camss`) with the Qualcomm® CAMX proprietary camera
framework. Board-level CAMX overlays (for example,
`qcs6490-rb3gen2-vision-mezzanine-camx.dtso`, `lemans-evk-camx.dtso`,
`monaco-evk-camx.dtso`) disable the upstream `camss` node and enable the CAMX
nodes. A combined `*-camx-el2.dtso` overlay is applied when both CAMX and KVM
are required simultaneously. The build system applies CAMX overlays when the
`VendorDtbOverlays` EFI variable is set to `camx`:

```bash theme={null}
echo -n "camx" > /tmp/overlay
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays \
    -w -f /tmp/overlay
efivar -n 882f8c2b-9646-435f-8de5-f208ff80c1bd-VendorDtbOverlays -p
sync && reboot
```

<Note>
  Use CAMX DTBs only when building with the Qualcomm proprietary camera stack.
  The upstream `camss` driver is disabled in CAMX configurations.
</Note>
