驱动开发硬核特训 · Day 21(下篇): 深入剖析 PCA9450 驱动如何接入 regulator 子系统
📘
一、设备树视角:PCA9450 是如何声明的?
设备树中定义了 PCA9450 芯片通过 I2C 总线挂载,并描述了多个 regulator 通道:
&i2c1 {pmic@25 {compatible = "nxp,pca9450c";reg = <0x25>;regulators {buck1: BUCK1 {regulator-name = "buck1";regulator-min-microvolt = <600000>;regulator-max-microvolt = <2187500>;regulator-boot-on;regulator-always-on;};ldo3: LDO3 {regulator-name = "ldo3";...};};};
};
每一个节点都会被解析为一个
regulator_desc
,并注册为一个独立的电源控制器。
二、驱动入口与注册流程分析
PCA9450 驱动本质上是一个 I2C Client 驱动 + regulator 注册器,核心结构如下:
static struct i2c_driver pca9450_i2c_driver = {.driver = {.name = "nxp-pca9450",.of_match_table = pca9450_of_match,},.probe = pca9450_i2c_probe,
};
在 pca9450_i2c_probe()
中:
- 初始化
regmap
与 IRQ - 解析 chip variant(A/B/C)
- 遍历每个
regulator_desc
调用devm_regulator_register()
注册通道
三、regulator 子系统对接流程
每个 BUCK/LDO 都有一个对应的 regulator_desc
,结构体中包括:
struct regulator_desc {const char *name;const struct regulator_ops *ops;unsigned int n_voltages;const struct linear_range *linear_ranges;unsigned int vsel_reg;unsigned int enable_reg;...
};
这些字段在注册时告诉 regulator 核心层:
- 如何读写电压
- 如何使能/禁用
- 有哪些支持的电压值
- 电压步进表
每个通道注册后,在 /sys/class/regulator/
下自动生成对应节点,供用户空间访问与调试。
四、regulator_ops 实现解读
PCA9450 中的 buck 与 ldo 由不同 regulator_ops
控制:
static const struct regulator_ops pca9450_buck_regulator_ops = {.enable = regulator_enable_regmap,.disable = regulator_disable_regmap,.set_voltage_sel = regulator_set_voltage_sel_regmap,.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
这些 ops 是标准封装 API,实际通过 regmap
映射访问硬件寄存器,实现驱动逻辑的模块化与通用性。
五、regmap 的作用
PCA9450 使用 regmap
框架读写 I2C 寄存器:
pca9450->regmap = devm_regmap_init_i2c(i2c, &pca9450_regmap_config);
regmap 帮我们做了:
- 地址映射与访问封装
- 缓存与同步机制
- 错误处理与调试辅助
简化了裸 I2C 通信过程,增强了可维护性。
六、小结:驱动与子系统的耦合点
元素 | 说明 |
---|---|
i2c_client 驱动 | 提供 probe/init 接口,获取设备资源 |
regulator_desc | 抽象每个电源输出的结构体 |
regulator_ops | 标准化的接口函数集 |
regmap | 注册表读写封装框架 |
regulator_register() | 向子系统注册一个电压输出通道 |
最终,PCA9450 将多个电源输出口封装为独立 regulator 通道,通过 regulator 子系统管理,并由设备树和用户空间灵活配置与控制。
七、工程启示与拓展思考
- 任何可调电源输出器件(如 TPS65090、AXP803)都可以通过 regulator 子系统驱动接入
- regulator 框架支持嵌套、动态电压控制、Suspend 设置等高级特性
- 对比其他子系统(如 input/net/sound),可以发现 Linux 内核在架构层面非常强调“接口抽象 + 解耦复用”
📌 如果你能透彻理解 PCA9450 驱动如何接入子系统,你也就掌握了开发高质量 Linux 驱动的核心精髓之一。
📺 视频教程请关注 B 站:“嵌入式 Jerry”