4. 设备树配置:节点编写、时钟与GPIO资源绑定、电源 regulator 配置
设备树,说白了就是硬件的“户口本”。Linux 内核通过它来认识你的 Sensor 接在哪个 I2C 总线上、用哪路时钟、需要多少电压。我刚开始接触 IMX 系列时,总觉得设备树就是填几个寄存器地址,后来踩了坑才明白——这里面的门道,比你想的深。
核心原则:设备树描述的是硬件连接关系,不是驱动逻辑。你写的是“Sensor 需要什么”,而不是“驱动怎么控制它”。
4.1 设备树节点的基本骨架
一个标准的 IMX Sensor 节点,通常长这样:
&i2c3 {
status = "okay";
imx335: camera@1a {
compatible = "sony,imx335";
reg = <0x1a>;
clocks = <&clks IMX8MM_CLK_CSI_MCLK>;
clock-names = "xvclk";
assigned-clocks = <&clks IMX8MM_CLK_CSI_MCLK>;
assigned-clock-rates = <24000000>;
reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
powerdown-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
avdd-supply = <®_avdd_2v8>;
dvdd-supply = <®_dvdd_1v2>;
ovdd-supply = <®_ovdd_1v8>;
port {
imx335_ep: endpoint {
remote-endpoint = <&csi_ep>;
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <480000000>;
};
};
};
};
这里有几个关键点,我一个个说。
4.2 时钟资源绑定——最容易翻车的地方
时钟配置是 Sensor 驱动的命脉。频率不对,图像直接花掉或者干脆没输出。我在一个项目中遇到过,IMX335 死活不出图,示波器一量——MCLK 只有 12MHz,而 Sensor 要 24MHz。
时钟绑定的三个要素:
- clocks:指定时钟源,通常是 SoC 的某个时钟输出引脚
- assigned-clocks:告诉内核,这个时钟我要接管
- assigned-clock-rates:直接设定目标频率,单位 Hz
我的习惯:在 assigned-clock-rates 里写死频率,而不是依赖 bootloader 或内核默认值。这样换内核版本也不怕。
不同 IMX Sensor 对时钟的要求差异很大:
| Sensor 型号 | 典型 MCLK 频率 | 时钟精度要求 | 备注 |
|---|---|---|---|
| IMX335 | 24MHz / 27MHz | ±1% | 支持内部 PLL 倍频 |
| IMX290 | 37.125MHz | ±0.5% | 对 jitter 敏感 |
| IMX378 | 24MHz | ±1% | 兼容性较好 |
| IMX415 | 27MHz / 54MHz | ±0.3% | 4K 模式要求高 |
4.3 GPIO 资源绑定——复位与电源管理的艺术
GPIO 在 Sensor 驱动里主要干两件事:复位和掉电控制。写错了,轻则初始化失败,重则烧芯片。
标准写法:
reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
powerdown-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
这里有个坑——极性定义。GPIO_ACTIVE_LOW 表示低电平有效,GPIO_ACTIVE_HIGH 表示高电平有效。不同 Sensor 的复位逻辑不一样:
- IMX335:复位低电平有效,拉低至少 1ms 再释放
- IMX290:复位低电平有效,但需要配合 XCLR 时序
- IMX378:复位高电平有效,跟上面两个正好相反
我曾经犯过的错:把 IMX290 的复位极性写反了,结果 Sensor 一直处于复位状态,I2C 通信全部 NACK。查了两天才发现是 GPIO_ACTIVE_LOW 写成了 GPIO_ACTIVE_HIGH。所以,拿到 datasheet 第一件事——确认复位极性。
4.4 电源 regulator 配置——电压不对,一切白费
IMX Sensor 通常需要三路供电:
| 电源名称 | 典型电压 | 用途 | 电流需求 |
|---|---|---|---|
| AVDD | 2.8V | 模拟电路供电 | ~100mA |
| DVDD | 1.2V | 数字核心供电 | ~200mA |
| OVDD | 1.8V | I/O 接口供电 | ~50mA |
设备树里通过 regulator 框架来管理:
avdd-supply = <®_avdd_2v8>;
dvdd-supply = <®_dvdd_1v2>;
ovdd-supply = <®_ovdd_1v8>;
这些 regulator 节点需要在设备树的其他地方定义:
reg_avdd_2v8: regulator-avdd {
compatible = "regulator-fixed";
regulator-name = "avdd_2v8";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
这里有个细节——上电时序。IMX 系列 Sensor 对上电顺序有严格要求,通常是 AVDD → DVDD → OVDD,或者同时上电。如果顺序反了,Sensor 内部可能会 latch-up。
我的做法:在驱动 probe 函数里,用 regulator_bulk_get 和 regulator_bulk_enable 来控制上电顺序。设备树只描述“用什么电源”,驱动控制“什么时候给电”。
4.5 知识结构总览
下面这张图,把设备树配置的核心逻辑串起来了:
4.6 避坑指南——我踩过的那些坑
做 IMX 驱动这几年,设备树配置上我栽过不少跟头。挑几个典型的说说:
- 时钟频率写错单位:assigned-clock-rates 的单位是 Hz,不是 MHz。我见过有人写 24 而不是 24000000,结果 Sensor 跑在 24Hz 上——画面当然不动。
- I2C 地址搞混:IMX335 的 7 位地址是 0x1a,但有些 datasheet 写的是 8 位地址 0x34。设备树里要用 7 位地址,这个坑我帮别人排查过好几次。
- 电源 regulator 没定义:在 Sensor 节点里引用了 regulator,但整个设备树里没定义这个 regulator 节点。内核会报 -EPROBE_DEFER,驱动永远 probe 不成功。
- data-lanes 顺序写反:MIPI CSI 的 data-lanes 顺序必须跟硬件 PCB 走线一致。写反了,图像数据错位,画面像万花筒。
重要提醒:设备树编译不会检查 GPIO 号、时钟索引、regulator 名称是否正确。写错了,编译通过,运行报错。所以,每次改完设备树,一定要用
devicetree-unittest 或者至少看内核启动日志里的 OF: ... 信息。
4.7 调试技巧——怎么验证设备树配对了
设备树配完,怎么知道对不对?我的三板斧:
- 看内核启动日志:grep "imx335\|camera\|of_probe" dmesg,看有没有 probe 成功
- 查 /sys/firmware/devicetree:直接看设备树解析出来的内容,跟你的配置对比
- 量波形:示波器量 MCLK、复位、电源,确认时序和电平对不对
嗯,设备树配置这部分就这些。记住一句话:设备树是硬件的“户口本”,写对了,驱动就成功了一半。