设备树学习2--一个设备

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的重点。

高通学习1-TLMM(TODO)-CSDN博客

高通学习2-QUP(TODO)_高通qup-CSDN博客

但是手上一直找不到高通的板子和代码,所以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";。

相关推荐
数智工坊2 小时前
【ROS 2 全栈入门指南三】:Action、参数与Launch文件全链路指南
android·stm32·嵌入式硬件·学习·机器人
Inhand陈工2 小时前
映翰通IG502实战:通过RS232采集交通信号灯数据,实现自动短信告警
网络·嵌入式硬件·物联网·网络安全·边缘计算·信息与通信·信号处理
不脱发的程序猿2 小时前
我把360里真正用得到的功能拆出来,做个轻量工具
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑2 小时前
嵌入式测试学习第 31 天:兼容性测试:版本兼容、外设兼容、硬件版本兼容
单片机·嵌入式硬件·学习
yongui478343 小时前
基于 STM32F103ZET6 的循轨避障蓝牙小车
stm32·单片机·嵌入式硬件
kebidaixu3 小时前
FreeRTOS 移植到 STM32F407VETX 记录(五)
stm32·单片机·嵌入式硬件
listhi5203 小时前
基于单片机的步进电机控制系统
单片机·嵌入式硬件
灯琰13 小时前
STM32L051K6U6 IAP要点记录-LL库
stm32·单片机·嵌入式硬件
MAR-Sky4 小时前
stc8h系列单片机使用中断号超过32的插件解决办法
单片机·嵌入式硬件