4. 设备树中的功耗相关属性

设备树(Device Tree)是嵌入式 Linux 系统中描述硬件拓扑和资源配置的核心机制。在功耗调优领域,设备树中的特定属性直接决定了 CPU/GPU 的动态调频策略、电源域管理、唤醒行为以及外部稳压器的控制方式。本章深入解析四个关键功耗属性:operating-points-v2、power-domains、wakeup-source 和 regulator,并阐述它们如何在驱动协同中发挥作用。

核心观点:设备树中的功耗属性不仅仅是静态描述,它们通过内核框架(如 OPP 框架、PM Domain 框架、Regulator 框架)与驱动层形成动态协同,是实现系统级功耗优化的基石。

4.1 operating-points-v2:动态调频与电压缩放

operating-points-v2 属性用于描述设备(通常是 CPU、GPU 或总线)支持的频率-电压组合,即工作点(Operating Performance Point, OPP)。它是 DVFS(Dynamic Voltage and Frequency Scaling)的硬件描述基础。

4.1.1 属性结构与绑定规则

该属性是一个 phandle,指向一个包含多个 OPP 子节点的表。每个子节点通过 opp-hz 和 opp-microvolt 定义频率与电压。可选的 opp-level、opp-suspend、turbo-mode 等标志用于细化策略。

cpu_opp_table: opp-table {
    compatible = "operating-points-v2";
    opp-shared;

    opp-996000000 {
        opp-hz = /bits/ 64 <996000000>;
        opp-microvolt = <1100000>;
        opp-suspend;
    };

    opp-800000000 {
        opp-hz = /bits/ 64 <800000000>;
        opp-microvolt = <1000000>;
    };

    opp-400000000 {
        opp-hz = /bits/ 64 <400000000>;
        opp-microvolt = <900000>;
        opp-level = <1>;
    };
};

cpu0: cpu@0 {
    compatible = "arm,cortex-a7";
    operating-points-v2 = <&cpu_opp_table>;
};

4.1.2 关键字段与功耗影响

字段 说明 功耗影响
opp-hz 工作频率(Hz) 频率越高,动态功耗(P ∝ f·V²)越大
opp-microvolt 工作电压(μV) 电压平方项对功耗影响最大
opp-suspend 挂起状态下的工作点 确保低功耗模式下电压足够维持状态
opp-level 性能等级(数值越小越省电) 用于调度器选择节能工作点
turbo-mode 短时爆发模式 允许短暂超频,但热约束严格
调优建议:在电池供电设备中,建议为 CPU 配置至少 3 个 OPP(高性能、平衡、低功耗),并通过 opp-level 让内核调度器优先选择低等级工作点。同时,利用 opp-suspend 确保系统挂起时电压不低于 retention 电压。

4.1.3 OPP 与 Regulator 的协同

OPP 框架通常与 Regulator 框架配合:当切换 OPP 时,内核通过 regulator_set_voltage 调整供电电压。设备树中通过 cpu-supply 属性关联 regulator 节点。

cpu0: cpu@0 {
    cpu-supply = <&vdd_cpu>;
    operating-points-v2 = <&cpu_opp_table>;
};
operating-points-v2 与 DVFS 协同流程 设备树 OPP 表 OPP 框架 CPUFreq 驱动 Regulator 框架 PMIC 硬件 时钟框架 解析 opp-hz / opp-microvolt

4.2 power-domains:电源域分层管理

power-domains 属性将设备关联到一个或多个电源域(Power Domain)。电源域是一个硬件分区,可以独立控制供电和时钟,实现细粒度的电源门控(Power Gating)。

4.2.1 电源域层级与属性绑定

电源域可以嵌套:父域关闭时,子域必须关闭。设备树中通过 power-domains 属性指定 phandle 和索引(用于多域设备)。

pd_display: power-domain@1 {
    compatible = "power-domain";
    #power-domain-cells = <0>;
    domain-idle-states = <&DISPLAY_WFI>;
};

pd_gpu: power-domain@2 {
    compatible = "power-domain";
    #power-domain-cells = <0>;
    power-domains = <&pd_top>;  /* 嵌套:GPU域属于顶层域 */
};

gpu: gpu@fde00000 {
    compatible = "arm,mali-g52";
    power-domains = <&pd_gpu>;
};

4.2.2 电源域状态与功耗收益

状态 描述 功耗节省 退出延迟
ON 全供电、全时钟 0% 0 μs
IDLE 时钟门控,保留电压 30-50% 1-10 μs
STANDBY 电压降低,保留状态 60-80% 10-100 μs
OFF 完全断电 99%+ 100 μs-1 ms
常见陷阱:嵌套电源域必须遵循“父域先于子域开启,子域先于父域关闭”的顺序。驱动中若未正确调用 pm_runtime_get_sync / pm_runtime_put_sync,可能导致父域提前关闭,造成子域设备数据丢失。

4.2.3 电源域与 Runtime PM 的协同

驱动通过 Runtime PM 框架与电源域交互。设备树中的 power-domains 属性自动触发 dev_pm_domain_attach,驱动只需实现 runtime_suspend / runtime_resume 回调。

电源域层级与设备绑定关系 pd_top (顶层域) pd_display (显示域) pd_gpu (GPU域) display-controller gpu 父域关闭 → 子域强制关闭

4.3 wakeup-source:唤醒能力声明

wakeup-source 是一个布尔属性,声明该设备在系统挂起(Suspend-to-RAM/Standby)期间能够唤醒系统。它通常与 GPIO 或 RTC 设备配合使用。

4.3.1 属性使用与驱动行为

当设备树中包含 wakeup-source 时,内核在设备初始化时自动调用 device_init_wakeup(dev, true),使能设备的唤醒能力。驱动在 suspend 回调中配置硬件中断为唤醒源。

gpio_keys: gpio-keys {
    compatible = "gpio-keys";
    pinctrl-names = "default";
    pinctrl-0 = <&key_pins>;

    power_key {
        label = "Power Key";
        gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
        linux,code = <KEY_POWER>;
        wakeup-source;  /* 声明该按键可唤醒系统 */
    };
};

4.3.2 唤醒源与功耗的平衡

唤醒源必须保持供电,因此会消耗一定的漏电流。设计时需权衡:

  • 优点:用户可通过按键、RTC 闹钟、网络包等事件唤醒系统,提升用户体验。
  • 代价:唤醒源所在的电源域不能完全断电,通常处于 STANDBY 状态,增加数微瓦到毫瓦级的静态功耗。
调优实践:在电池设备中,只对必要的唤醒源(如电源键、RTC)设置 wakeup-source,避免将触摸屏、传感器等非关键设备标记为唤醒源。同时,通过 /sys/devices/.../power/wakeup 接口可在运行时动态禁用唤醒能力。

4.4 regulator 属性:电压调节器绑定

Regulator 属性用于将设备与其供电的电压调节器(PMIC 或 LDO)关联。常见的属性包括 cpu-supply、vdd-supply、vcc-supply 等,命名规则为 <名称>-supply。

4.4.1 属性绑定与电压协商

设备驱动通过 regulator_get 获取 regulator 句柄,然后调用 regulator_set_voltage 和 regulator_enable 控制供电。设备树中的 regulator-* 属性定义了电压范围、启动延迟等约束。

vdd_cpu: regulator@0 {
    compatible = "regulator-fixed";
    regulator-name = "vdd_cpu";
    regulator-min-microvolt = <900000>;
    regulator-max-microvolt = <1300000>;
    regulator-always-on;  /* 保持常开(不推荐用于DVFS) */
};

&cpu0 {
    cpu-supply = <&vdd_cpu>;
};

4.4.2 Regulator 与 OPP 的电压匹配

当 OPP 切换时,内核会调用 regulator_set_voltage 将电压调整到 opp-microvolt 指定的值。如果 regulator 不支持该电压(超出 min/max 范围),OPP 切换会失败,系统可能崩溃。

场景 设备树配置 驱动行为 功耗影响
固定电压 regulator-always-on 不动态调压 高(电压恒定)
动态调压 无 always-on,设置 min/max OPP 切换时调压 低(电压随频率变化)
电压范围过窄 min/max 差距小 OPP 切换可能失败 系统不稳定
关键约束:Regulator 的电压切换时间(ramp delay)必须在设备树中正确设置。如果 ramp delay 过大,CPU 频率提升后电压尚未到位,会导致逻辑错误。通常 ramp delay 应小于 10 μs。
Regulator 与 OPP 电压协商流程 设备树 OPP 表 OPP 框架 Regulator 驱动 PMIC 硬件 检查 opp-microvolt 是否在 regulator 范围内

4.5 四个属性的协同工作模式

在实际系统中,这四个属性往往协同工作,形成一个完整的功耗管理链路:

  1. Regulator 提供电压调节能力,由设备树中的 *-supply 属性绑定。
  2. operating-points-v2 定义频率-电压组合,驱动通过 OPP 框架请求调频调压。
  3. power-domains 控制设备的电源门控,在空闲时关闭整个域。
  4. wakeup-source 确保关键设备在系统挂起时仍能唤醒系统。
实战案例:某智能音箱项目通过设备树配置 CPU 的 OPP 表(3 个工作点)、将 WiFi 模块放入独立电源域并标记为 wakeup-source、使用可调压 regulator 供电,最终实现待机功耗从 1.2W 降至 0.3W,同时保持语音唤醒功能。