I am working on a Qualcomm-based ARM SoC and need to define the interconnects between peripherals in the Device Tree (.dts).
From my understanding, the interconnects property is used to describe NoC (Network-on-Chip) paths between different components (e.g., CPU, memory, GPU, and peripherals). However, I am struggling with:
Example of my current DT snippet:
i2c@78b6000 {
compatible = "qcom,i2c-gen3";
reg = <0x78b6000 0x1000>;
clocks = <&rpmhcc RPMH_APPS_CLK>;
interconnects = <&mnoc MASTER_I2C SLAVE_DDR>;
interconnect-names = "dma-mem";
};
Questions:
Any guidance or working examples would be greatly appreciated!
The interconnect framework in the Linux kernel provides a way to model Network-on-Chip (NoC) connections and manage bandwidth between different system components. This is especially useful for Qualcomm-based ARM SoCs, where interconnect paths affect performance and power efficiency.
An interconnect path in DT describes the connection between a master (initiator, e.g., I2C, GPU) and a slave (target, e.g., DDR, SRAM). The property interconnects
is used to define this relationship.
The interconnect framework in the Linux kernel provides a way to model Network-on-Chip (NoC) connections and manage bandwidth between different system components. This is especially useful for Qualcomm-based ARM SoCs, where interconnect paths affect performance and power efficiency.
1. Defining an Interconnect in Device Tree (DT)
An interconnect path in DT describes the connection between a master (initiator, e.g., I2C, GPU) and a slave (target, e.g., DDR, SRAM). The property interconnects is used to define this relationship.
Example: I2C Controller with an Interconnect Path
i2c@78b6000 {
compatible = "qcom,i2c-gen3";
reg = <0x78b6000 0x1000>;
clocks = <&rpmhcc RPMH_APPS_CLK>;
/* Interconnect path: I2C master -> Memory (DDR) */
interconnects = <&mnoc MASTER_I2C SLAVE_DDR>;
interconnect-names = "dma-mem";
};
Explanation:
interconnects = <&mnoc MASTER_I2C SLAVE_DDR>;
&mnoc → Reference to the NoC node handling the interconnect.
MASTER_I2C → The initiator (I2C controller).
SLAVE_DDR → The target (DDR memory).
interconnect-names = "dma-mem";
This provides a human-readable identifier for the interconnect path.
2. Referencing an Interconnect Node in a Device Node
Most device drivers that require interconnect support will use the interconnects property.
For instance, a GPU node referencing an interconnect path:
gpu@5000000 {
compatible = "qcom,adreno-gpu";
reg = <0x5000000 0x10000>;
interconnects = <&bimc MASTER_GPU SLAVE_DDR>;
interconnect-names = "gpu-mem";
};
This ensures that when the GPU needs memory bandwidth, it requests an interconnect path dynamically.
3. Kernel-Side Dependencies & Bindings
The interconnect framework relies on the drivers/interconnect/ subsystem in the Linux kernel.
Qualcomm's implementation uses interconnect-qcom.c, which registers NoC paths for Snapdragon SoCs.
Ensure your kernel configuration includes:
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
4. Verifying Interconnect Configuration at Runtime
You can check interconnect settings using sysfs/debugfs:
ls /sys/class/interconnect/
cat /sys/kernel/debug/interconnect/*/*
To check active bandwidth requests:
cat /sys/kernel/debug/interconnect/summary
This will display the current bandwidth requests and active NoC paths.
5. Best Practices for Power & Performance Optimization
Tune bandwidth dynamically: Drivers should request bandwidth only when needed and scale down when idle to save power.
Use OPP tables: For SoCs supporting performance states, link interconnect scaling with Operating Performance Points (OPP).
Monitor power impact: Use powertop and pmqos to profile bandwidth efficiency.
Final Thoughts
Your interconnects property definition for the I2C controller is correct.
The debugging steps will help confirm if the paths are active in the kernel.
The kernel.org interconnect framework ensures SoCs can dynamically manage bandwidth, optimizing both performance and power efficiency.
References:
Interconnect Framework - Kernel.org
Qualcomm Interconnect Driver (Linux)