在现代 SoC 设计中,电源域(Power Domain)是精细化功耗管理的核心支撑单元。随着芯片工艺进入 7nm 及以下,静态漏电功耗占比显著上升,独立控制各功能模块的电源通断成为能效优化的关键手段。GENPD(Generic Power Domain)作为 Linux 内核电源管理子系统的中层框架,上承 Runtime PM 与系统挂起机制,下接硬件电源控制逻辑,构建了一套统一的电源域抽象与调度体系。
GENPD 框架的核心价值体现在三个层面:

随着 SoC 集成度的不断提升,一颗芯片往往集成了 CPU、GPU、NPU、ISP、VPU、多媒体编解码器等数十个功能模块。如果所有模块共享同一电源轨,将导致两个严重问题:
为解决这些问题,现代 SoC 普遍采用多电源域设计,将芯片划分为若干个可独立上电/断电的逻辑区域。但这又引入了新的复杂度:
GENPD 框架位于 drivers/base/power/domain.c,是内核电源管理体系的中间层:
GENPD 框架的核心抽象围绕以下关键数据结构展开:

这是电源域的核心表示结构,每个电源域对应一个实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 struct generic_pm_domain { const char *name; /* 电源域名称 */struct dev_pm_domain domain; /* PM 域基类 */ /* 状态管理 */ unsigned int flags; /* 域属性标志 */ bool powered_off; /* 当前是否断电 */ int device_count; /* 域内设备数量 */ int prepared_count; /* 已准备设备计数 */ /* 引用计数 */ atomic_t refcount; /* 激活引用计数 */ /* 硬件操作回调 */ int (*power_on)(struct generic_pm_domain *domain); int (*power_off)(struct generic_pm_domain *domain); int (*attach_dev)(struct generic_pm_domain *domain,struct device *dev); void (*detach_dev)(struct generic_pm_domain *domain,struct device *dev); /* 层级关系 */struct generic_pm_domain *parent; /* 父电源域 */struct list_head child_links; /* 子域链表 */ /* 域内设备 */struct list_head dev_list; /* 挂载设备链表 */ /* Governor */struct dev_power_governor *gov; /* 性能状态 */struct dev_pm_opp *opps; unsigned int state_count;struct gpd_power_state *states; /* 统计信息 */ ktime_t on_time; ktime_t off_time; u64 on_time_ns; u64 off_time_ns;};
每个挂载到电源域的设备对应一个实例,用于追踪设备状态:
1 2 3 4 5 6 7 8 struct generic_pm_domain_data {struct pm_domain_data base;struct generic_pm_domain *domain; unsigned int refcount; /* 设备级引用计数 */ bool need_restore; /* 唤醒时是否需要恢复 */struct list_head list_node; /* 域设备链表节点 */};
用于设备树绑定的 onecell 风格数据结构,管理一组电源域:
1 2 3 4 5 6 struct genpd_onecell_data {struct generic_pm_domain **domains; /* 电源域数组 */ unsigned int num_domains; /* 域数量 */ unsigned int domain_index; /* 当前索引 */};
GENPD 框架采用分层设计模型,自上而下分为三层:



pm_runtime 接口即可间接操作电源域定义了清晰的状态转换模型:
平台驱动通过以下接口向 GENPD 核心注册电源域:

关键函数调用序列:
1 2 3 4 5 6 pm_genpd_init() └→ 初始化锁、链表、统计信息 └→ 设置默认 governor └→ 初始状态设置 └→ list_add(&domain->gpd_list_node, &gpd_list)
设备通过设备树的 power-domains 属性完成绑定:



GENPD 通过 struct dev_pm_domain 机制无缝集成到 Runtime PM 体系中。当设备绑定到电源域后,其 dev->pm_domain 被替换为 GENPD 提供的操作集:
1 2 3 4 5 6 7 8 9 10 11 12 staticstruct dev_pm_domain genpd_dev_pm_ops = { .runtime_suspend = genpd_runtime_suspend, .runtime_resume = genpd_runtime_resume, .runtime_idle = genpd_runtime_idle, .suspend_noirq = genpd_suspend_noirq, .resume_noirq = genpd_resume_noirq, .freeze_noirq = genpd_freeze_noirq, .thaw_noirq = genpd_thaw_noirq, .prepare = genpd_prepare, .complete = genpd_complete,};
这种设计使得设备驱动无需感知电源域的存在,继续使用标准的 pm_runtime_get/put 接口即可自动触发电源域的状态转换。
在系统挂起的 suspend_noirq 阶段,GENPD 执行以下操作:
在系统唤醒的 resume_noirq 阶段执行逆操作:
GENPD 在内核 late_initcall 阶段注册了 genpd_poweroff_unused 工作项,定期扫描所有电源域,自动关闭没有设备挂载或所有设备都已空闲的电源域,确保系统启动后闲置的电源域不会白白消耗电力。
GENPD 支持可插拔的电源管理 Governor,用于决策是否允许电源域断电。默认提供两种策略:
pm_domain_always_on_gov:始终保持上电,不允许断电pm_domain_qos_governor:根据 QoS 约束决定是否断电平台可以根据功耗和延迟需求选择或自定义 Governor。
RK3588 采用精细化的电源域划分设计,芯片内部划分为 20+ 个独立电源域,由 PMU(Power Management Unit)统一控制。关键电源域包括:

RK3588 内核设备树中(rk3588.dtsi),电源域控制器定义如下:
1 2 3 4 5 6 7 power: power-controller@fdc20000 { compatible = "rockchip,rk3588-pm-domains"; reg = <0x0 0xfdc20000 0x0 0x1000>; #power-domain-cells = <1>; status = "okay";};
设备绑定电源域的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 &gpu { power-domains = <&power RK3588_PD_GPU>; power-supply = <&vdd_gpu>; status = "okay";};&npu { power-domains = <&power RK3588_PD_NPU>; power-supply = <&vdd_npu>; status = "okay";};&venc { power-domains = <&power RK3588_PD_VENC>; power-supply = <&vdd_logic>; status = "okay";};
RK3588 的电源域驱动位于 drivers/soc/rockchip/pm_domains.c,核心实现包括:
generic_pm_domain 实例典型的上电操作序列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int rockchip_pd_power_on(struct generic_pm_domain *domain){struct rockchip_pm_domain *pd = to_rockchip_pd(domain); /* 1. 使能时钟 */ clk_bulk_enable(pd->num_clks, pd->clks); /* 2. 解除复位 */ reset_control_deassert(pd->rst); /* 3. 解除电源隔离 */ regmap_update_bits(pd->pmu, PD_ISO_CTRL_REG, pd->iso_mask, 0); return 0;}
对应的断电操作则执行逆操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int rockchip_pd_power_off(struct generic_pm_domain *domain){struct rockchip_pm_domain *pd = to_rockchip_pd(domain); /* 1. 设置电源隔离 */ regmap_update_bits(pd->pmu, PD_ISO_CTRL_REG, pd->iso_mask, pd->iso_mask); /* 2. 置位复位 */ reset_control_assert(pd->rst); /* 3. 关闭时钟 */ clk_bulk_disable(pd->num_clks, pd->clks); return 0;}
RK3588 的电源域并非完全独立,而是存在明确的层级依赖关系:

这种层级关系通过 generic_pm_domain.parent 指针建立,GENPD 核心在处理电源状态转换时会自动遵循这些约束。例如,GPU 域上电前必须确保 PD_LOGIC 域已激活,而 PD_LOGIC 断电前必须确保 GPU、NPU、VPU 等所有子域均已关闭。
通过 debugfs 可以查看 RK3588 各电源域的实时状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 cat /sys/kernel/debug/pm_genpd/pm_genpd_summaryDomain Status #devices idle_time--------------------------------------------------------pd_cpu_big0 on 4 0mspd_cpu_big1 on 4 0mspd_cpu_lit on 4 0mspd_gpu off 1 12500mspd_npu off 1 12500mspd_venc off 1 12500mspd_vdec off 1 12500mspd_vi off 1 12500mspd_vo off 1 12500ms
这表明系统中 CPU 集群处于工作状态,而 GPU、NPU、多媒体编解码等模块所在的电源域均已断电,累计空闲时间约 12.5 秒。
GENPD 电源域框架是 Linux 内核精细化功耗管理的基石,其核心设计可概括为:
struct generic_pm_domain 统一表示所有电源域GENPD 的设计体现了嵌入式系统典型的权衡艺术: