1 概述
分析一个实际看到的例子。整体是2万多行,看着挺唬人的,不过分步骤来看,主要是下面几个部分。

整体就是ddr-regions,chosen,memory,reserved-memory,aliases,firmware,cpus,idle-states,soc,symbols,hypervisor。
这里就分为普通和soc两个部分吧。
2 一般信息部分
其实这个部分也不是普通,只是相对没那么重点。所以就一次说完。
2.1 平台基础信息
首先是平台基础信息。包含了
硬件名称:高通 NEO Aliso SG2 开发板(IDP = 原厂参考设计板);
msm-id/board-id:高通平台芯片 / 板级唯一标识,驱动、固件、分区表依赖此匹配。
2.2 内存分区
之后是内存分区。
(1)ddr-regions DDR 内存区域划分
定义物理内存分段,用于系统、固件、外设内存隔离,是高通平台标准内存分区表。
(2)memory 主内存节点
reg 一长串地址 = 系统可用物理内存分段,ARM64 大内存布局,拆分多段物理内存块,供内核动态管理。
(3)reserved-memory 保留内存(重点!嵌入式核心)
整块标记 no-map,内核普通地址空间不可访问,专门预留给各类固件、安全域、多媒体、调试区,是高通移动端 SoC 典型设计。内部如下:
| 节点名称 | 用途 |
|---|---|
hyp_region |
Hypervisor 虚拟化 / TrustZone 安全监控器内存(安卓安全环境) |
xbl_* |
XBL 高通一级引导程序(Bootloader)日志 / 转存区 |
aop_* |
AOP 音频 / 低功耗协处理器固件内存 |
smem_region |
高通共享内存(AP/CP/ 各子系统跨核通信) |
adsp/cdsp |
音频 DSP、计算 DSP 固件运行内存 |
gpu_microcode |
GPU 微码内存 |
video/camera_region |
摄像头、视频编解码专用缓存 |
qtee_region |
QTEE 高通可信执行环境(安全 OS)内存 |
ramoops |
内核崩溃日志保存区(掉电不丢,用于调试宕机) |
linux,cma |
Linux CMA 连续内存分配器(给 DMA、摄像头、GPU 分配大块连续内存) |
各类 shared-dma-pool |
DMA 共享内存池(外设零拷贝传输) |
2.3 chosen启动参数节点
(内核启动核心)
bootargs = "xxx"; stdout-path = "/soc/qcom,qupv3_1_geni_se@ac000/qcom,qup_uart@a94000:115200n8";
这里包括了bootargs:内核命令行参数。stdout-path:系统默认串口控制台。
2.4 别名节点aliases
给硬件外设起短别名,方便内核 / 应用引用:
serial0/1/hsuart0:多路串口别名;
mmc0:SD/EMMC 存储别名;
swr0~3:SWR 音频总线别名。
3 多核&功耗基础子系统
3.1 cpus 处理器集群
cpus {
cpu@0 ~ cpu@3 四颗CPU核心
enable-method = "psci";
}
这里表示:4 核 ARM 架构(Kryo 高通自研核心);
psci:ARM 标准电源 / 核控制接口(开关 CPU、休眠、热插拔);
每颗 CPU 绑定 L2/L3 缓存、功耗域、调频域。
3.2 idle-states内核休眠状态
定义了CPU/集群多级休眠。
pc/rail-pc:CPU 浅休眠;
l3-off/cx-off:关闭 L3 缓存、电源域深度休眠;
控制唤醒延迟、最小驻留时间,移动端低功耗核心配置。
4 SOC片上外设总容器
这个就是最大的部分。首先是中断、时钟、电源三大基础框架(SoC 底座)
4.1 interrupt-controller@1720000 GIC-V3 中断控制器
ARM64 标准 GICv3 通用中断控制器;
所有外设中断、CPU 间中断都由它统一管理,整个系统中断路由核心。
4.2 时钟控制器(gcc/camcc/dispcc/videocc/gpucc)
高通平台分多个独立时钟域:
gcc:全局时钟(总线、系统、PCIe、USB);
camcc:摄像头时钟;
dispcc:显示时钟;
videocc:视频编解码时钟;
gpucc:GPU 时钟;
每个时钟域独立门控、调频,按需开关时钟省电。
4.3 RPMh 电源管理(rsc 节点)
rsc@af2000 / rsc@17a0000 = RPMh 高通高级电源管理器
移动端核心功耗管理单元;
管理各路 LDO、BUCK 稳压电源、电压域(CX/MX/LLCC 等);
节点内大量 rpmh-regulator-xxx:一路路稳压输出,给 GPU、摄像头、DSP、USB、PCIe 等外设单独供电;
支持动态调压、休眠断电,是手机 / 嵌入式低功耗的核心。
4.4 thermal-zones温控系统
整颗 SoC温度监控 & 温控:
分区:主 CPU、GPU、NSP、音频、摄像头、PMIC 电源芯片、DDR 等独立测温区;
配置多级温度阈值:预警、过热、临界关机;
搭配降温策略(降频、限流),防止芯片烧毁。
下面是重点外设控制器。
4.5 PinCtrl + GPIO 引脚控制器(pinctrl@f000000)
这是整份设备树体量最大的节点,也是之前学习 pinctrl / GPIO 的对应硬件层:
兼容 qcom,neo-pinctrl:高通新一代引脚控制器;
具备三大能力:GPIO 控制器 + 中断控制器 + 引脚复用 (MUX);
内部海量 pin 配置组:
每一组对应一个外设的引脚复用、电气参数(上下拉、驱动强度、电平);
格式:xxx_active(外设工作模式) + xxx_sleep(外设休眠模式),两套配置切换;
典型复用分组(高频外设)
qupv3_xx_i2c / qupv3_xx_spi / qupv3_xx_uart:QUP 控制器切换为 I2C/SPI/UART(高通通用多功能外设);
sdc1:SD/EMMC 卡引脚配置;
usb0_phy:USB 物理层引脚;
pcie0/pcie1:PCIe 复位、时钟、唤醒引脚;
audio 相关 I2S/TDM:音频数字接口;
camera_mclk:摄像头时钟引脚;
蓝牙、WiFi 使能、复位引脚等。
4.6 QUP多功能控制器
高通 QUP (Qualcomm Universal Peripheral) 是平台特色:
一个硬件控制器可动态切换为 UART / I2C / SPI,设备树里通过 pinctrl 引脚复用 + 驱动匹配实现切换。
文档中大量 qupv3_seX 都是 QUP 实例,对应多路串口、I2C、SPI。
4.7 多媒体子系统
(1)GPU qcom,kgsl-3d0
compatible = qcom,kgsl-3d0 / qcom,adreno-gpu-a621:Adreno 621 GPU;
包含 GPU 寄存器、GMU (GPU 管理单元)、SMMU 内存管理单元、GPU 调频 / 功率档位;
对应 Linux DRM/KMS 显示框架(之前学习的 DRM、fb 驱动底层硬件)。
(2)视频 / 图像
venus 视频编解码、camera 摄像头控制器;
搭配专用电源、时钟、保留内存,是安卓多媒体核心。
4.8 数字信号处理器(DSP/远程处理器)
高通平台典型异构多核架构,AP (主 Linux) + 多个协处理器:
remoteproc-adsp:音频 DSP(ADSP),运行音频固件;
remoteproc-cd:计算 DSP(CDSP),语音 / AI 算法;
通信方式:glink / ipcc / smem 核间通信;
Linux 端通过 remoteproc 驱动加载固件、启停协处理器。
4.9 存储 & 总线
sdhci@7C4000:SD/EMMC 主机(手机 / 开发板闪存);
spi / i2c:由 QUP 复用而来;
qcom,qcedev:硬件加密引擎(加解密、哈希,安卓安全 / 支付使用);
qrng:硬件真随机数发生器。
4.10 通信&辅助模块
spmi:与外部 PMIC 电源芯片通信总线;
glink / ipcc / smp2p:多核 / 多子系统消息、数据通道;
qfprom:芯片 OTP 一次性可编程存储器(存芯片序列号、GPU 速度 BIN、校准数据);
eud:USB 附属功能;
mini_dump:系统宕机迷你转存调试。
5 其它
其它1
这里有一些没有compatible的部分,比如ddr-regions,chosen。这种写法不符合Linux驱动标准内容。

这里可能是前期初始完DDR之后,直接写入到设备树中。在Linux初始化开始时,此时内存管理单元 MMU 甚至可能还没完全建立,常规驱动框架根本还没初始化。所以直接使用硬编码读取。
比如:
cpp
struct device_node *node = of_find_node_by_path("/ddr-regions");
if (node) {
// 直接显式读取 region0 和 region1 的属性值
of_property_read_u32_array(node, "region0", ...);
of_property_read_u32_array(node, "region1", ...);
// 将读取到的物理内存区间和拓扑结构上报给内核的内存管理系统
}
所以,设备树不仅是给常规设备驱动(如 I2C、SPI、DRM 显卡)做 match 用的,它还是引导程序(Bootloader)与 Linux 内核核心(Kernel Core)之间进行极早期大块数据交接的"共享内存缓冲区"。
其它2
像这种格式,有意义吗?
cpus {
#address-cells = <0x02>;
#size-cells = <0x00>;
查了一下也是有的,只是不给驱动用的也是内核使用of_find_node_by_path("/cpus")直接查询,系统有几个核心。
此外CPU还有驱动?比如compatible = "qcom,kryo"。这里其实不是CPU本身的驱动,而是算力调度,热量调度,性能调度(DVFS/EAS)等。这里会加载高通特有的 qcom-cpufreq-hw 驱动来进行处理。
在真实设备树中,大概有以下三类节点。
-
有
compatible且对应.ko/ 传统外设驱动 :如compatible = "qcom,qup-uart"。在编译完内核后,你会得到一个独立的驱动模块,通过insmod xxx.ko点亮它。 -
有
compatible但不对应.ko(核心框架配置) :如compatible = "arm,idle-state"或compatible = "arm,gic-v3"(中断控制器)。它们由内核核心代码在极早期直接接管,无法作为模块拔插。 -
完全没有
compatible(纯共享缓冲区路径) :如上面讲的ddr-regions {或chosen {。内核完全通过显式路径(Explicit Path)像查字典一样去肉眼读取数据。
其它3
大概看了下,最大的两个部分,一个是Pinctrl,另外一个是qupv3。
pinctrl在高通平台上被称为TLMM (Top Level Mode Multiplexer,顶级引脚模式多路复用器)。它是整个芯片所有物理引脚(GPIO)的"大总管"。
芯片上的那几百个金属管脚(Pins),本身是没有任何定义的。通过设置 TLMM 寄存器,你可以让 GPIO_10 变成串口的 TX 线,也可以让它变成控制屏幕复位的 RST 线,或者变成一个普通的按键输入。
qupv3是高通独有的Qualcomm Universal Peripheral v3 (高通第三代通用外设总线包装器)。它是将低速通信外设(UART、SPI、I2C、I3C)全部整合在一起的硬核硬件总线。
其实这两部分之前都想写写的,这两个部分其实也是Bringup的重点。
但是手上一直找不到高通的板子和代码,所以TODO了非常久了。
总的来说:
pinctrl是控制"硬件引脚电路怎么连、怎么导通"的地图总入口。
qupv3系列是控制"大核 Linux 怎么给各类传感器、蓝牙、普通屏幕发指令"的数据总线入口。
| 特性维度 | pinctrl(TLMM 引脚控制) | qup(Geni 串行引擎) |
|---|---|---|
| 所处层级 | 物理层 / 电气层 | 协议层 / 数据链路层 |
| 核心职责 | 管引脚的死活、走向、电压、电流。 | 管数据的协议、时序、波特率、打包。 |
| 在干什么 | 1. 切换引脚复用(是做 GPIO 还是给串口用)。 2. 控制内部上下拉电阻。 3. 调节引脚的驱动电流(驱动能力)。 | 1. 把并行的 CPU 数据转成串行的比特流。 2. 按照标准的 SPI/I2C/UART 协议发信号。 3. 配合 BAM DMA 进行免 CPU 的大块数据吞吐。 |
| 设备树属性特征 | pins = "gpio10"; function = "qup10"; drive-strength = <12>; |
reg = <0xa90000 0x4000>; clock-frequency = <19200000>; dmas = <&bamdma 5>; |
| 坏了的表现 | 用示波器去量引脚,完全没有任何波形,或者高电平电压不够(信号塌陷)。 | 用示波器能量到时钟波形,但时序不对、波特率错了,导致设备报校验错误(CRC/ACK Error)。 |
其它4
最后有一个这个
symbols {
slimbus = "/soc/slim@3340000/ngd@1/btfmslim-driver";
bluetooth = "/soc/bt_kiwi";
bt_en_sleep = "/soc/pinctrl@f000000/bt_en_sleep";
ipclite_vpu = "/soc/ipclite/vpu";
ipclite_cvp = "/soc/ipclite/cvp";
ipclite_cdsp = "/soc/ipclite/cdsp";
...
这个主要是为了不重新编译庞大的主 DTB,可能会写一个轻量级的 .dtbo 插件。比如想在蓝牙节点下面追加入参,.dtbo 会这样写。
bash
&bluetooth {
qcom,new-property = <1>;
};
此时&bluetooth这个节点对应的就是在 symbols 里记录了:bluetooth = "/soc/bt_kiwi";。
