Runtime PM管理也就是設備驅動里面的電源管理,即設備驅動結構體里面的struct dev_pm_ops,只控制設備自己的電源。這樣可以在設備不需要工作的時候可以進入到低功耗狀態,更好的管理設備自己的電源,所謂:“各掃門前雪”。
為什么需要Runtime PM?
不同于系統的電源管理,設備自己的電源管理更加的細化。這就像一個層級關系,系統整體的是一個大的電源狀態管理,但是對于眾多的集成外國設備也不能一刀切,就是不能要干活都干活要休息都休息,要細化管理不能懶政,就對每個設備自己也來一套電源狀態管理,直接把機制從系統哪里復制過來一份一個閹割版的就夠用,采用分而治之的思想,只要系統要統一指揮的時候聽話就可以,其他時候可以自己決策執行就是runtime PM管理。這里的設備有可能是外設,比如sensor、lcdc等。這里的設備也有可能是SOC內部的某些IP,比如codec、dsp、usb等。
1. 框架介紹
1.1 為什么需要Runtime PM Framework?
系統基本的電源管理,例如關機休眠等,需要調用device的電源Runtime API就是ops回調函數,而且需要按一個順序的queue去實施,而且系統跟設備狀態發生沖突的時候也需要去處理,綜上就需要一個Framework去統一做這些事情
設備驅動需要根據系統的一些參數來決定自己的電源狀態,例如CPU是否idle等,就需要系統框架的支持
當設備處于低功耗模式時,wakeup signal常常需要platform或者bus的支持。
1.2 系統框架圖
數據結構:
image.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); static int __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不太一樣,它是針對單個設備,指系統在非睡眠狀態的情況下,某個設備在空閑時可以進入運行時掛起狀態,而在不是空閑時執行運行時恢復使得設備進入正常工作狀態,如此,這個設備在運行時會省電。
每個設備處理好自己的電源管理,在不需要工作時進入低功耗狀態。也就是"各人自掃門前雪"。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,則導致該看門狗設備的運行時掛起。
在一些設備上不使用的時候不能立即掛起,,因為掛起狀態的進入和恢復需要一些時間,如果設備不在掛起之間保留一定的時間,頻繁進出掛起反而會帶來新的開銷。因此,我們可根據情況決定只有設備在空閑了一段時間后才進入掛起(一般來說,一個一段時間沒有被使用的設備,還會有一段時間不會被使用),基于此,一些設備驅動也常常使用自動掛動模式進行編程。
在執行操作的時候聲明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設備。
/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,為驅動程序增加一個電源管理的功能,會更加的靈活,也是我們去優化系統功耗的一個重要方向。因為大多數程序估計是供應商提供的,但是我們自己的加的硬件的程序估計是我們自己去寫的,并且做業務挺耗電,給自己寫的驅動加個電源管理就挺好。
-
電源管理
+關注
關注
117文章
6432瀏覽量
146098 -
cpu
+關注
關注
68文章
11076瀏覽量
216998 -
soc
+關注
關注
38文章
4386瀏覽量
222678 -
函數
+關注
關注
3文章
4379瀏覽量
64827 -
runtime
+關注
關注
0文章
17瀏覽量
2289
原文標題:電源管理入門-16 驅動Runtime PM管理
文章出處:【微信號:OS與AUTOSAR研究,微信公眾號:OS與AUTOSAR研究】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
Linux電源管理:Runtime PM的軟件框架

電源管理入門:Thermal熱管理

電源管理入門:Power Domain管理

電源管理入門:Hypervisor中的電源管理

Linux電源管理的系統架構和驅動
Linux電源管理之Generic PM Suspend功能簡析
需要了解的Linux中電源管理接口
Linux電源管理--PM QoS

評論