一、整体最高观
在 i.MX8MP 设备树 (DTS)中,如 LCDIF1 模块,使用了 power-domain 属性:
lcdif1: lcd-controller@32e80000 {
compatible = "fsl,imx8mp-lcdif1";
reg = <0x32e80000 0x10000>;
clocks = <...>;
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>;
status = "disabled";
};
而在驱动编写中,是不需要手动处理 power-domain 的,全部由设备模型和 GENPD 框架自动完成。
而 LCDIFv3 驱动以 platform_driver
形式注册,使用 pm_runtime
框架,通过 runtime suspend/resume 自动管理下段实际的 power domain 开关。
这套机制,就是现代高级驱动编写的标准。
二、高清统一流程图
设备树(DTS) 指定 power-domains
↓
platform_device_register()
↓
pm_genpd_add_device(dev)
↓
自动绑定对应的 Power Domain 控制器
↓
驱动中 pm_runtime_enable(dev)
↓
Runtime期间:
pm_runtime_get/put(自动 power on/off)
↓
GENPD 框架通过硬件实际执行
三、核心驱动分析:imx-lcdifv3
步骤 | 代码分析 |
---|---|
1 | 读取 clock 资源: devm_clk_get() |
2 | pm_runtime_enable(dev) |
3 | imx_lcdifv3_runtime_resume() 打开 power-domain |
4 | imx_lcdifv3_runtime_suspend() 关闭 power-domain |
四、具体分段分析
(一) platform_driver 注册
注册时配置好 probe/remove/pm_ops:
struct platform_driver imx_lcdifv3_driver = {
.probe = imx_lcdifv3_probe,
.remove = imx_lcdifv3_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = imx_lcdifv3_dt_ids,
.pm = &imx_lcdifv3_pm_ops,
},
};
(二) probe 函数:imx_lcdifv3_probe()
核心注意点:
- devm_clk_get 读取相关 clock
- devm_ioremap_resource 映射 IO 地址
- pm_runtime_enable 启用 runtime pm
- platform_set_drvdata 设置驱动私有数据
以下是关键代码:
pm_runtime_enable(dev);
atomic_inc(&lcdifv3->rpm_suspended);
表示“该设备支持 runtime pm,后续自动管理下电、上电”
(三) Runtime 常规操作:
suspend :关闭当前 power domain
static int imx_lcdifv3_runtime_suspend(struct device *dev)
{
lcdifv3_disable_clocks(lcdifv3);
release_bus_freq(BUS_FREQ_HIGH);
}
- 关闭 clock
- 通知开始关闭当前的 Power-domain
resume :打开当前 power domain
static int imx_lcdifv3_runtime_resume(struct device *dev)
{
request_bus_freq(BUS_FREQ_HIGH);
lcdifv3_enable_clocks(lcdifv3);
}
- 打开 clock
- 通知开始打开 power-domain
五、具体示例:LCDIF1 设备树与驱动对应
1. 设备树中
lcdif1: lcd-controller@32e80000 {
compatible = "fsl,imx8mp-lcdif1";
reg = <0x32e80000 0x10000>;
clocks = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT>,
<&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
clock-names = "pix", "disp-axi";
power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>;
};
2. 驱动 probe 时
pm_runtime_enable(dev);
最后所有开关都被 GENPD 框架管理。
3. 执行下电的链路:
power-domain runtime suspend
↓
imx_lcdifv3_runtime_suspend
↓
lcdifv3_disable_clocks
↓
关闭 pixel clock,disp axi clock
保证硬件完全下电,达到节能效果。
六、这套机制有什么优势?
特性 | 说明 |
---|---|
全基于 DTS | 硬件依赖被设备树管理 |
级联 GENPD | 合并全局的 Power Domain 资源 |
高级 runtime PM | 自动实时节能 |
驱动无需自处理 | 简化代码,降低错误率 |
七、实战建议:BSP工程师思路
当你在对接 SoC时,应该根据以下思路:
- 查询设备树中 power-domains
- 确认是否有 GENPD 控制器
- 驱动中 pm_runtime_enable()
- 需要控制时,通过 pm_runtime_get/put 管理
- 遵循 runtime suspend/resume 连接 GENPD 逻辑
八、总结
LCDIFv3 驱动中,实际不用直接管 power domain,所有操作都通过 platform framework + runtime PM + GENPD 来完成!
完全完全完全是 完全自动系统,驱动只需做好自己属于设备框架的部分!