0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心
发布

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

电源管理入门:驱动Runtime PM管理

yzcdx 来源:OS与AUTOSAR研究 2023-11-29 10:13 次阅读

Runtime PM管理也就是设备驱动里面的电源管理,即设备驱动结构体里面的struct dev_pm_ops,只控制设备自己的电源。这样可以在设备不需要工作的时候可以进入到低功耗状态,更好的管理设备自己的电源,所谓:“各扫门前雪”。

为什么需要Runtime PM?

不同于系统的电源管理,设备自己的电源管理更加的细化。这就像一个层级关系,系统整体的是一个大的电源状态管理,但是对于众多的集成外国设备也不能一刀切,就是不能要干活都干活要休息都休息,要细化管理不能懒政,就对每个设备自己也来一套电源状态管理,直接把机制从系统哪里复制过来一份一个阉割版的就够用,采用分而治之的思想,只要系统要统一指挥的时候听话就可以,其他时候可以自己决策执行就是runtime PM管理。这里的设备有可能是外设,比如sensor、lcdc等。这里的设备也有可能是SOC内部的某些IP,比如codec、dspusb等。

1. 框架介绍

1.1 为什么需要Runtime PM Framework?

系统基本的电源管理,例如关机休眠等,需要调用device的电源Runtime API就是ops回调函数,而且需要按一个顺序的queue去实施,而且系统跟设备状态发生冲突的时候也需要去处理,综上就需要一个Framework去统一做这些事情

设备驱动需要根据系统的一些参数来决定自己的电源状态,例如CPU是否idle等,就需要系统框架的支持

当设备处于低功耗模式时,wakeup signal常常需要platform或者bus的支持。

1.2 系统框架图

3f1a5378-8dda-11ee-939d-92fbcf53809c.png

数据结构:

3f326544-8dda-11ee-939d-92fbcf53809c.png

image.png

关机举例:

3f575624-8dda-11ee-939d-92fbcf53809c.png

休眠举例:

3f6d659a-8dda-11ee-939d-92fbcf53809c.png

2. Drivers

Device drivers(包括bus、class、power domain)实现了runtime pm相关的runtime_idle/runtime_suspend/runtime_resume三个回调:

runtime_suspend用于实现设备的低功耗操作

runtime_resume用于实现设备的低功耗恢复相关的操作

runtime_idle属于runtime_suspend的一个过渡,用于缓冲频繁的suspend与resume,它会判断设备是否具备suspend的条件,如果具备在合适的时机,就会suspend设备。

runtime_suspend与runtime_resume回调函数里会调用clock framework/reset framework/regulator framework提供的时钟开关、复位、电源开关接口。这里以SPI驱动为例进行说明:

subsys_initcall(pl022_init); staticint __init pl022_init(void) { return amba_driver_register(&pl022_driver); } static struct amba_driver pl022_driver = { .drv = { .name = "ssp-pl022", .pm = &pl022_dev_pm_ops, }, .id_table = pl022_ids, .probe = pl022_probe, .remove = pl022_remove, }; static const struct dev_pm_ops pl022_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume) SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) }; #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) .runtime_suspend = suspend_fn, .runtime_resume = resume_fn, .runtime_idle = idle_fn,

pm结构体dev_pm_ops 中的有3个以runtime开头的成员函数:runtime_suspend()、runtime_resume()和runtime_idle(),它们辅助设备完成运行时的电源管理

struct dev_pm_ops { ... int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); ... };

运行时的PM与前文描述的系统级挂起到RAM时候的PM不太一样,它是针对单个设备,指系统在非睡眠状态的情况下,某个设备在空闲时可以进入运行时挂起状态,而在不是空闲时执行运行时恢复使得设备进入正常工作状态,如此,这个设备在运行时会省电。

3f8f8fda-8dda-11ee-939d-92fbcf53809c.png

每个设备处理好自己的电源管理,在不需要工作时进入低功耗状态。也就是"各人自扫门前雪"。Linux提供了一系列API,以便于设备可以声明自己的运行时PM状态:

函数名字 功能
pm_runtime_suspend 引发设备的挂起,执行相关的runtime_suspend()函数。
pm_schedule_suspend “调度”设备的挂起,延迟delay毫秒后将挂起工作挂入pm_wq等待队列,结果等价于delay毫秒后执行相关的runtime_suspend()函数。
pm_runtime_resume 引发设备的恢复,执行相关的runtime_resume()函数。
pm_request_resume 发起一个设备恢复的请求,该请求也是挂入pm_wq等待队列。
pm_runtime_idle 引发设备的空闲,执行相关的runtime_idle()函数。
pm_request_idle 发起一个设备空闲的请求,该请求也是挂入pm_wq等待队列。
pm_runtime_enable 使能设备的运行时PM支持。
pm_runtime_disable 禁止设备的运行时PM支持。
pm_runtime_getpm_runtime_get_sync 增加设备的引用计数(usage_count),这类似于clk_get(),会间接引发设备的runtime_resume()。
pm_runtime_putpm_runtime_put_sync 减小设备的引用计数,这类似于clk_put(),会间接引发设备的runtime_idle()。

3. Runtime PM core

Runtime pm core主要提供了三类函数接口:

提供enable/disable接口给设备驱动,用于该设备驱动决定是否打开或关闭RPM,

提供get、put类接口给设备驱动,用于决定什么时候进入或者恢复设备低功耗,

在设备驱动调用了get、put接口后RPM会调用各设备驱动实现的runtime_suspend/runtime_resume接口

对于决定设备是否进入低功耗的get/put接口的调用时机,一般会在操作设备相关寄存器前调用get接口,在操作完相关寄存器后调用put接口。或者在设备驱动的open、release、start、stop等接口里调用,用户层的services通过ioctrl或者驱动提供的文件节点调用驱动的这些接口。

我们可以这样简单地理解Linux运行时PM的机制,每个设备(总线的控制器自身也属于一个设备)都 有引用计数usage_count和活跃子设备(Active Children,子设备的意思就是该级总线上挂的设备)计数child_count,当两个计数都为0的时候,就进入空闲状态,调用pm_request_idle(dev)。

当设备进入空闲状态,与pm_request_idle(dev)对应的PM核并不一定直接调用设备驱动的runtime_suspend(),它实际上在多数情况下是调用与该设备对应的bus_type的runtime_idle()。

在具体的设备驱动中,一般的用法则是在设备驱动probe()时运行pm_runtime_enable()使能运行时PM支持,在运行过程中动态地执行“pm_runtime_get_xxx()->做工作->pm_runtime_put_xxx()”的序列。如代码清单19.19中的drivers/watchdog/omap_wdt.c OMAP的看门狗驱动。

在omap_wdt_start()中启动了pm_runtime_get_sync(),

而在omap_wdt_stop()中调用了pm_runtime_put_sync()。

static const struct watchdog_ops omap_wdt_ops = { .owner = THIS_MODULE, .start = omap_wdt_start, .stop = omap_wdt_stop, .ping = omap_wdt_ping, .set_timeout = omap_wdt_set_timeout, .get_timeleft = omap_wdt_get_timeleft, }; static int omap_wdt_start(struct watchdog_device *wdog) { pm_runtime_get_sync(wdev->dev);//告诉内核要开始用看门狗这个设备了,如果看门狗设备已经进入省电模式(之前引用计数为0且执行了运行时挂起),会导致该设备的运行时恢复 static int omap_wdt_stop(struct watchdog_device *wdog) { pm_runtime_put_sync(wdev->dev);//告诉内核不用这个设备了,如果引用计数变为0且活跃子设备为0,则导致该看门狗设备的运行时挂起。

在一些设备上不使用的时候不能立即挂起,,因为挂起状态的进入和恢复需要一些时间,如果设备不在挂起之间保留一定的时间,频繁进出挂起反而会带来新的开销。因此,我们可根据情况决定只有设备在空闲了一段时间后才进入挂起(一般来说,一个一段时间没有被使用的设备,还会有一段时间不会被使用),基于此,一些设备驱动也常常使用自动挂动模式进行编程

3fa8a93e-8dda-11ee-939d-92fbcf53809c.png

在执行操作的时候声明pm_runtime_get(),操作完成后执行pm_runtime_mark_last_busy()和pm_runtime_put_autosuspend(),一旦自动挂动的延时到期且设备的使用计数为0,则引发相关runtime_suspend()入口函数的调用。

设备驱动PM成员的runtime_suspend()一般完成保存上下文、切到省电模式的工作,而runtime_resume()一般完成对硬件上电、恢复上下文的工作

4. power domain framework

一个power domain上可能包含多个IP,每个IP可能对应一个或多个设备。这些设备会在dts中描述与power domain的绑定关系。系统初始化的时候,会将这个power domain放到一个链表中,然后根据设备中dts描述的与power domain的关系,将设备挂在power domain节点下的链表中。

当某个设备驱动通过put接口调用,将usage_count从1减少到0,这时会先调用power domain注册的runtime_suspend接口,在这个接口中,会先调用该设备驱动的runtime_suspend,然后遍历该power domain下所有的设备是否都允许suspend(各设备驱动的usage_count是否为0),若允许就会直接调用关闭power domian的接口,否则直接返回。当某个设备驱动通过get接口调用,将usage_count从0增加到1,这时会先调用power domain注册的runtime_resume接口,在这个接口中,会先将power domain上电,然后再调用设备驱动对应的runtime_resume回调函数,让设备退出低功耗。

5. runtime pm的sysfs

对于支持rpm的设备,在相应的设备节点下有多个rpm相关属性的文件节点,分别为control,runtime_susupend_time,runtime_active_time,autosuspend_delay_ms,runtime_status。接口在文件: /kernel/drivers/base/power/sysfs.c中描述。

/sys/devices/.../power/control

on - 调用pm_runtime_forbid接口,增加设备的引用计数,然后resume设备。

auto - 调用pm_runtime_allow接口,减少设备的引用计数,如果设备的引用计数为0,则idle设备。

3fcbb53c-8dda-11ee-939d-92fbcf53809c.png

/sys/devices/.../power/runtime_status

active - 设备的状态是正常工作状态。

suspend- 设备的状态是低功耗模式。

suspending-设备的状态正在从active->suspend转化。

resuming-设备的状态正在从suspend->active转化。

error-设备runtime出现错误,此时runtime_error的标志置位。

unsupported-设备的runtime 没有使能,此时disable_depth标志置位。

/sys/devices/.../power/runtime_suspend_time

设备在suspend状态的时间

/sys/devices/.../power/runtime_active_time

设备在active状态的时间

/sys/devices/.../power/autosuspend_delay_ms

设备在idle状态多久之后suspend,设置延迟suspend的延迟时间。

后记:

在编写驱动的时候,如果涉及电源管理的功耗需求,就需要实现struct dev_pm_ops,为驱动程序增加一个电源管理的功能,会更加的灵活,也是我们去优化系统功耗的一个重要方向。因为大多数程序估计是供应商提供的,但是我们自己的加的硬件的程序估计是我们自己去写的,并且做业务挺耗电,给自己写的驱动加个电源管理就挺好。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电源管理
    +关注

    关注

    114

    文章

    6084

    浏览量

    142822
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10640

    浏览量

    208667
  • soc
    soc
    +关注

    关注

    38

    文章

    3978

    浏览量

    216704
  • 函数
    +关注

    关注

    3

    文章

    4214

    浏览量

    61849
  • runtime
    +关注

    关注

    0

    文章

    17

    浏览量

    2151

原文标题:电源管理入门-16 驱动Runtime PM管理

文章出处:【微信号:OS与AUTOSAR研究,微信公众号:OS与AUTOSAR研究】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux电源管理RuntimePM的软件框架

    device driver(或者driver所在的bus、class等)需要提供3个回调函数, runtime_suspend、 runtime_resume和 runtime_idle,分别用于suspend device、resu
    发表于09-15 15:57 2061次阅读
    Linux<b class='flag-5'>电源</b><b class='flag-5'>管理</b>:<b class='flag-5'>Runtime</b> <b class='flag-5'>PM</b>的软件框架

    电源管理入门-Regulator驱动是什么?Regulator的作用是什么?

    Regulator是Linux系统中 电源 管理的基础设施之一,用于稳压 电源管理,是各种 驱动子系统中设置 电压的标准接口。
    的头像 发表于11-16 16:51 6617次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-Regulator<b class='flag-5'>驱动</b>是什么?Regulator的作用是什么?

    电源管理入门:Thermal热管理

    管理指的是在电子设备或系统中通过各种方式控制其温度来保证其正常工作或延长寿命的过程。其中包括散热设计、温度监测、温度控制等方面。热 管理的重要性越来越凸显,尤其在高性能计算、人工智能等领域的应用中更为重要。
    的头像 发表于11-29 10:09 2769次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Thermal热<b class='flag-5'>管理</b>

    电源管理入门:Power supply子系统

    对于便携设备来说, 电源 管理更加的重要,因为电池电量有限,容易电量焦虑。除了省电 管理外,还需要对电池进行监控 管理和充放电 管理,这样保护好电池和
    的头像 发表于11-29 10:15 3013次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Power supply子系统

    电源管理入门:Power Domain管理

    SoC中通常有很多IP,按逻辑可以把几个相关功能的IP划为一个 电源域。一个 电源域内的IP,通常按相同的方式由同一个硬件模块PMIC供电,电压一样并且 电源 管理例如休眠唤醒一致。
    的头像 发表于11-29 10:16 2391次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Power Domain<b class='flag-5'>管理</b>

    电源管理入门-芯片设计中的电源管理介绍

    SCP直接控制SoC的 电源和时钟,而AP通过硬件和软件接口协同 管理
    的头像 发表于12-06 09:16 2089次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-芯片设计中的<b class='flag-5'>电源</b><b class='flag-5'>管理</b>介绍

    电源管理入门:Hypervisor中的电源管理

    很多时候听说Hypervisor,但是对底层软件技术不了解的人感觉挺神秘。本篇文章简单介绍下Hypervisor的基本概念,另外介绍下 电源 管理在Hypervisor之上多OS间怎么应用。
    的头像 发表于12-06 09:27 1112次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Hypervisor中的<b class='flag-5'>电源</b><b class='flag-5'>管理</b>

    LINUX电源管理的相关资料分享

    Linux的系统suspend和resumeLinux内核 runtime_PM框架Linux内核 电源 管理综述
    发表于11-15 07:10

    如何对PCI设备的电源进行管理

    1 PCI设备的 电源 管理PCI设备的 电源 管理包括系统 PMruntime
    发表于12-27 07:17

    Linux电源管理的系统架构和驱动

    ,牵扯到系统级的待机、频率电压变换、系统空闲时的处理以及每个设备 驱动对系统待机的支持和每个设备的运行时( Runtime) 电源 管理,可以说它和系统中的每个设备
    发表于01-03 06:36

    Linux电源管理之GenericPMSuspend功能简析

    管理接口”的描述。设备 驱动----具体设备 驱动的位置,不再涉及。3)平台依赖PMinclude/linux/suspend.h----定义平台依赖 PM相关的操作函数集arch/xxx/
    发表于08-10 15:20

    LINUX电源管理

    Linux的系统suspend和resumeLinux内核 runtime_PM框架Linux内核 电源 管理综述
    发表于11-07 19:36 8次下载
    LINUX<b class='flag-5'>电源</b><b class='flag-5'>管理</b>

    Linux电源管理--PMQoS

    (requester)。 PMQoS framework针对两种对象分别提供了 电源 管理的基础框架和接口。 那么在 电源 管理的范畴内要如何理解服
    发表于01-05 14:37 1次下载
    Linux<b class='flag-5'>电源</b><b class='flag-5'>管理</b>--<b class='flag-5'>PM</b> QoS

    PCI设备的电源管理

    1 PCI设备的 电源 管理PCI设备的 电源 管理包括系统 PMruntime
    发表于01-05 14:37 3次下载
    PCI设备的<b class='flag-5'>电源</b><b class='flag-5'>管理</b>

    驱动篇:inux电源管理的系统架构和驱动(一)

    ,牵扯到系统级的待机、频率电压变换、系统空闲时的处理以及每个设备 驱动对系统待机的支持和每个设备的运行时( Runtime) 电源 管理,可以说它和系统中的每个设备
    发表于01-11 16:03 11次下载
    <b class='flag-5'>驱动</b>篇:inux <b class='flag-5'>电源</b><b class='flag-5'>管理</b>的系统架构和<b class='flag-5'>驱动</b>(一)