SoC中通常有很多IP,按邏輯可以把幾個(gè)相關(guān)功能的IP劃為一個(gè)電源域。一個(gè)電源域內(nèi)的IP,通常按相同的方式由同一個(gè)硬件模塊PMIC供電,電壓一樣并且電源管理例如休眠喚醒一致。
為什么有設(shè)備電源管理還需要power domain劃分?
對(duì)每個(gè)設(shè)備電源管理太細(xì)化了,會(huì)造成額外的開(kāi)銷(xiāo)。通常幾個(gè)設(shè)備可以一塊進(jìn)行管理更加的方便,例如一個(gè)子系統(tǒng),要么全工作要么全關(guān)閉,不會(huì)子系統(tǒng)內(nèi)的某個(gè)設(shè)備單獨(dú)工作。這時(shí)候?yàn)榱撕?jiǎn)化管理工作就需要?jiǎng)澐殖鰜?lái)一個(gè)domain。SOC上眾多電源域組成了一個(gè)電源域樹(shù),他們之間存在著相互的約束關(guān)系,子電源域打開(kāi)前,需要父電源域打開(kāi),父電源域下所有子電源域關(guān)閉,父電源域才能關(guān)閉。
Domain這個(gè)詞一般在權(quán)限管理中經(jīng)常遇到,用于隔離,Domain內(nèi)共進(jìn)退。
雖然電源域的好處多多,卻不是越多越好,因?yàn)閯澐蛛娫从蚴?strong>需要成本的(需要在PMU中使用模擬電路完成,包括金錢(qián)成本和空間成本)。因此,大多數(shù)系統(tǒng)會(huì)根據(jù)功能,設(shè)置有限的幾個(gè)電源域,例如:CPU core(1、2、3…);GPU;NAND;DDR;USB;Display;Codec等等。
這種設(shè)計(jì)引出一個(gè)問(wèn)題:存在多個(gè)模塊共用一個(gè)電源域的情況。因而要求在對(duì)模塊power on/off的時(shí)候,考慮power共用的情況:只要一個(gè)模塊工作,就要power on;直到所有模塊停止工作,才能power off。
1. 框架介紹
Kernel的PM domain framework(位于drivers/base/power/domain.c中),提供了管理和使用系統(tǒng)power domain的統(tǒng)一方法:
對(duì)底層power domain硬件的操作
對(duì)power domain hw的開(kāi)啟操作,包括開(kāi)鐘、上電、解復(fù)位、解除電源隔離等操作的功能封裝;
對(duì)power domain hw的關(guān)閉操作,包括關(guān)鐘、斷電、復(fù)位、做電源隔離等操作的功能封裝;
內(nèi)部邏輯實(shí)現(xiàn)
通過(guò)dts描述power domain框架的設(shè)備節(jié)點(diǎn),并描述每個(gè)power domain節(jié)點(diǎn)。提供出一個(gè)power domain framework的設(shè)備節(jié)點(diǎn),及每個(gè)power domain子設(shè)備的節(jié)點(diǎn),并指定power-domain-ccell = <1>,這樣可以通過(guò)power domain framework的設(shè)備及power domain的編號(hào)查找具體的power domain;
實(shí)現(xiàn)dts解析邏輯,獲取power domain的配置信息,并通過(guò)初始化函數(shù)對(duì)每個(gè)power domain進(jìn)行初始化,所有的power domain統(tǒng)一的放在一個(gè)全局鏈表中,將power domain下所有的設(shè)備,放到其下的一個(gè)設(shè)備鏈表中;
為runtime pm、系統(tǒng)休眠喚醒等框架,注冊(cè)相應(yīng)的回調(diào)函數(shù),并實(shí)現(xiàn)具體的回調(diào)函數(shù)對(duì)應(yīng)的power domain的開(kāi)關(guān)函數(shù);
上層使用power domain的上游驅(qū)動(dòng)、框架及debug fs
linux系統(tǒng)的runtime power manager 框架通過(guò)提供runtime_pm_get_xxx/runtime_pm_put_xxx類(lèi)接口給其他的drivers,對(duì)設(shè)備的開(kāi)、關(guān)做引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)從1->0時(shí),會(huì)進(jìn)一步調(diào)到power domain注冊(cè)的runtime_suspend回調(diào),回調(diào)函數(shù)里會(huì)先調(diào)用設(shè)備的runtime_suspend回調(diào),然后判斷power domain下的設(shè)備鏈表中所有的設(shè)備是否已經(jīng)suspend,若已經(jīng)suspend才真正關(guān)閉power domain。當(dāng)引用計(jì)數(shù)從0->1時(shí),會(huì)先調(diào)用到power domain使用的runtime_resume回調(diào),回調(diào)函數(shù)里會(huì)先調(diào)用power domain的開(kāi)啟操作,然后調(diào)用設(shè)備注冊(cè)的runtime_resume回調(diào)函數(shù);
系統(tǒng)休眠喚醒在suspend_noirq/resume_noirq時(shí)會(huì)進(jìn)行power domain的關(guān)閉與開(kāi)啟的操作;
使用power domain的上游驅(qū)動(dòng):power domain內(nèi)部ip的驅(qū)動(dòng)。比如,dsp子系統(tǒng)power domain下面,有多個(gè)dsp核,每個(gè)dsp核對(duì)應(yīng)一個(gè)power domain。這樣,每個(gè)dsp核設(shè)備驅(qū)動(dòng)都要關(guān)聯(lián)到對(duì)應(yīng)的dsp核power domain上,通過(guò)dsp核設(shè)備的dts里power-domains的屬性引用(power domain framework的節(jié)點(diǎn)引用及具體power domain的編號(hào)),將dsp核設(shè)備與相應(yīng)的power domain關(guān)聯(lián)起來(lái);
使用power domain的框架:runtime pm/系統(tǒng)休眠喚醒;
power domain也提供了一些debug fs文件節(jié)點(diǎn)供用戶debug使用,主要就是/sys/kernel/debug/pm_genpd/目錄及power domain名字目錄下的一些文件節(jié)點(diǎn):
pm_genpd_summary:打印所有的power domain、狀態(tài)及下面所掛的設(shè)備狀態(tài)
power_domain名字目錄/current_state:power domain當(dāng)前的狀態(tài)
power_domain名字目錄/sub_domains:power domain當(dāng)前的子power domain有哪些
power_domain名字目錄/idle_states:power domain對(duì)應(yīng)的所有idle狀態(tài)及其off狀態(tài)的時(shí)間
power_domain名字目錄/active_states:power domain處于on狀態(tài)的時(shí)間
power_domain名字目錄/total_idle_time:power domain所有idle狀態(tài)的off時(shí)間總和
power_domain名字目錄/devices:power domain下所掛的所有devices
相關(guān)數(shù)據(jù)結(jié)構(gòu):
image.png
初始化流程(以scmi power domain的驅(qū)動(dòng)框架為例):
image.png
2. 如何使用power domain
在dts中定義一個(gè)power domain節(jié)點(diǎn),同時(shí)在驅(qū)動(dòng)中注冊(cè)該power domain即可
//DTS中定義powerdomain節(jié)點(diǎn),這里以內(nèi)核文檔提供的例程 parent:power-controller@12340000{ compatible="foo,power-controller"; reg=<0x12340000?0x1000>; #power-domain-cells=<1>;//這里表明parent節(jié)點(diǎn)是一個(gè)powerdomain,也就是內(nèi)核文檔所形容的provider,parent管理它下面掛接著的其它模塊,為它們提供電源 }; child:power-controller@12341000{ compatible="foo,power-controller"; reg=<0x12341000?0x1000>; power-domains=<&parent?0>;//這里表明child節(jié)點(diǎn)是parent下面的一個(gè)模塊,它使用parent提供的電源 #power-domain-cells=<1>; };
從上面的dts語(yǔ)法中可以看出,一個(gè)系統(tǒng)的電源域從dts中可以很容易就看出來(lái),#power-domain-cells聲明該節(jié)點(diǎn)是一個(gè)power domain,power-domains = <&xxx x>表明該節(jié)點(diǎn)屬于xxx電源域,那么系統(tǒng)中某個(gè)電源域下面有多少個(gè)模塊就從dts中看有多少個(gè)節(jié)點(diǎn)引用了該電源域即可。
3. provider
intpm_genpd_init(structgeneric_pm_domain*genpd, structdev_power_governor*gov,boolis_off)//初始化一個(gè)generic_pm_domain實(shí)例 //下面兩個(gè)接口都可以用來(lái)向內(nèi)核注冊(cè)一個(gè)powerdomian intof_genpd_add_provider_onecell(structdevice_node*np, structgenpd_onecell_data*data) intof_genpd_add_provider_simple(structdevice_node*np, structgeneric_pm_domain*genpd)
pm_genpd_init這個(gè)函數(shù)從注釋可以看出它初始化了一個(gè)power domain實(shí)例,從入口參數(shù)結(jié)合具體的實(shí)現(xiàn)代碼,可以很容易得到 structgeneric_pm_domain結(jié)構(gòu)體就對(duì)應(yīng)著一個(gè)power domain實(shí)例。
structgeneric_pm_domain{ structdev_pm_domaindomain;/*PMdomainoperations*/ constchar*name; atomic_tsd_count;/*Numberofsubdomainswithpower"on"*/ enumgpd_statusstatus;/*Currentstateofthedomain*/ unsignedintdevice_count;/*Numberofdevices*/ unsignedintsuspended_count;/*Systemsuspenddevicecounter*/ unsignedintprepared_count;/*Suspendcounterofprepareddevices*/ int(*power_off)(structgeneric_pm_domain*domain);//驅(qū)動(dòng)只要實(shí)現(xiàn)該函數(shù)即可 int(*power_on)(structgeneric_pm_domain*domain);//驅(qū)動(dòng)只要實(shí)現(xiàn)該函數(shù)即可
真正需要驅(qū)動(dòng)去賦值的成員只有兩個(gè),那就是int (*power_off)(struct generic_pm_domain *domain); 與int (*power_on)(struct generic_pm_domain *domain);,其它的power domain framework已經(jīng)幫我們做好了,這里我們也可以猜到一個(gè)電源域的打開(kāi)與關(guān)閉最終是通過(guò)驅(qū)動(dòng)注冊(cè)的這兩個(gè)函數(shù)操作的,
當(dāng)驅(qū)動(dòng)得到一個(gè)power domain實(shí)例后,便可以調(diào)用of_genpd_add_provider_simple函數(shù)向內(nèi)核注冊(cè)一個(gè)power domain了,來(lái)進(jìn)入該函數(shù)看看,做了哪些事情,看不太懂,但是從入口參數(shù)看,傳進(jìn)去了驅(qū)動(dòng)實(shí)現(xiàn)的struct generic_pm_domain和power domain的node節(jié)點(diǎn)。后續(xù)這兩個(gè)參數(shù)應(yīng)該會(huì)有作用。
4. Consumer
Cousumer可能是一個(gè)驅(qū)動(dòng)程序或者sysfs,在驅(qū)動(dòng)probe函數(shù)中調(diào)用dev_pm_domain_attach
ret=dev_pm_domain_attach(_dev,true);//將設(shè)備與電源域進(jìn)行耦合
驅(qū)動(dòng)在probe的時(shí)候會(huì)調(diào)用dev_pm_domain_attach函數(shù)檢查設(shè)備是否屬于power domain設(shè)備,如果是,則獲取設(shè)備的power domain信息,從哪里獲取信息?就是從前面power domain驅(qū)動(dòng)調(diào)用of_genpd_add_provider_simple函數(shù)注冊(cè)進(jìn)來(lái)的信息。
調(diào)用genpd_add_device函數(shù),將設(shè)備添加到該power domain中,主要完成一些struct generic_pm_domain成員的賦值操作。
最后最重要的就是調(diào)用dev_pm_domain_set該函數(shù),設(shè)置了struct device中的struct dev_pm_domain成員,該成員被賦值為struct generic_pm_domain中的struct dev_pm_domain成員。
后記
power domain在底層的處理通常需要PPU硬件的參與管理,可以控制這個(gè)電源域的時(shí)鐘、電壓、供電等屬性,從而達(dá)到對(duì)電源和功耗的管理。
-
電源管理
+關(guān)注
關(guān)注
117文章
6400瀏覽量
145796 -
soc
+關(guān)注
關(guān)注
38文章
4345瀏覽量
221756 -
Power
+關(guān)注
關(guān)注
1文章
502瀏覽量
68429 -
PMIC
+關(guān)注
關(guān)注
15文章
401瀏覽量
110960
原文標(biāo)題:參考:
文章出處:【微信號(hào):OS與AUTOSAR研究,微信公眾號(hào):OS與AUTOSAR研究】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
電源管理入門(mén)-關(guān)機(jī)重啟基礎(chǔ)知識(shí)詳解

電源管理入門(mén)-什么是OPP?怎么用?

電源管理入門(mén)-Regulator驅(qū)動(dòng)是什么?Regulator的作用是什么?

電源管理入門(mén):Thermal熱管理

電源管理入門(mén):驅(qū)動(dòng)Runtime PM管理

電源管理入門(mén):Power supply子系統(tǒng)

電源管理入門(mén):Hypervisor中的電源管理

UPF流程與電源域Power Domain詳解
電源管理芯片簡(jiǎn)述
PMU電池管理配置與io-domain電源域的相關(guān)資料推薦
ARM GIC(七)gicv3架構(gòu)提供的power管理功能
PMU電池管理配置與io-domain電源域

Linux系統(tǒng)進(jìn)程管理入門(mén)指南

評(píng)論