Linux電源管理(15)_PM OPP Interface

1. 前言

本文是分析cpufreq framework之前的一篇前置文章,用於介紹Linux電源管理中的Operating Performance Point (OPP)接口。

OPP是一個單純的軟件library,用於歸納、管理各個硬件模塊的、可工作的{頻率}/ {電壓}組合。它不涉及任何硬件,也沒有複雜的邏輯,再加上Kernel document(Documentation/power/opp.txt )描述的非常清晰,因此本文只是簡單的從功能和API兩個方便介紹OPP,不再分析其source code及內部實現邏輯。

2. 功能說明

2.1 什麼是OPP

“Documentation/power/opp.txt ”中解釋OPP的原話(我翻譯了一下)是:

當前複雜的SoCs都包括多個協同工作的子模塊。根據具體的應用場景,很多子模塊(蝸蝸注:典型的例子是CPU)並不需要一直工作在最高的頻率上。因此SoC中的子模塊劃分爲不同的domains,允許一些domains在較低的電壓/頻率下工作,而另一些在較高的電壓/頻率下工作。

domain中的設備支持的所有頻率和電壓的組合,稱作Operating Performance Points,簡稱爲OPPs。

注1:爲什麼一定是頻率和電壓的組合?因爲頻率高低決定器件的工作性能,降低性能的目的是節省功耗。但頻率對功耗的影響是有限的,而電壓對功耗的影響卻相當可觀。那頻率和電壓有什麼關係呢?通常情況下,當頻率降低之後,器件的工作電壓也是可以降低的(回憶一下數字電路)。因此不同的“頻率/電壓”組合,就組成了器件在性能和功耗之間的蹺蹺板,我們需要做的,就是根據實際場景,選擇一個合適的組合。

2.2 使用場景

對具備多個OPP的設備而言,相關的使用場景包括:

1)需要一個三維數組,保存所有的OPPs。

2)可以方便的更改OPP條目。

3)當需要改變設備的OPP時,可以方便的查詢設備支持哪些OPP。

4)可以通過一定的條件查詢OPP信息,例如以頻率值查詢、以電壓值查詢、以頻率或者電壓範圍查詢等等。

5)其它需求。

其實蠻簡單的,但考慮到這些需求對所有設備(應該也不是很多)都是相同,kernel就抽象出來一個library--就是OPP library,實現上述功能。具體可參考後續的描述。

2.3 實現思路

試下OPP library的主要思路,就是以設備爲單位,管理OPP信息。如下(摘錄自Documentation/power/opp.txt ):

*  
* Internal data structure organization with the OPP layer library is as 
* follows:  
* dev_opp_list (root)  
*      |- device 1 (represents voltage domain 1)  
*      |       |- opp 1 (availability, freq, voltage)  
*      |       |- opp 2 ..  
*      ...     ...  
*      |       `- opp n ..  
*      |- device 2 (represents the next voltage domain)  
*      ...  
*      `- device m (represents mth voltage domain)  
* device 1, 2.. are represented by dev_opp structure while each opp  
* is represented by the opp structure.  
*/

按理說,可以在設備指針(struct device)中,添加一個字段,用於保存該設備的OPP列表。但OPP人微言輕,無法打入設備模型的內部,只好自己處理了。就是上面的結構:

在OPP內部(drivers/base/power/opp.c)維護一個list,用於保存每個設備的OPP信息(由struct device_opp抽象),每個設備下面,維護了所有的OPP列表(由struct dev_pm_opp結構抽象)。所有的OPP操作,都會從root list開始遍歷,直到找到合適的地方爲止。

struct device_opp和struct dev_pm_opp只在OPP library的內部使用,不會把細節呈現給調用者,因爲本文不會過多涉及OPP library的內部實現(比較簡單),所以後面就不再描述這些結構了。

3. 接口說明

OPP library的source code位於drivers/base/power/opp.c中,header位於include/linux/pm_opp.h中,提供的接口包括(本文基於linux-3.18-rc4,其它版本的文件名或者接口名可能會有些不同):

   1: int dev_pm_opp_add(struct device *dev, unsigned long freq,
   2:                    unsigned long u_volt);

向指定的設備添加一個頻率/電壓組合,OPP library會在內部處理好所有事情。這裏頻率和電壓的單位分別是Hz和uV,後面都是這個單位。

   1: int dev_pm_opp_enable(struct device *dev, unsigned long freq);
   2:  
   3: int dev_pm_opp_disable(struct device *dev, unsigned long freq);

雖然設備支持某些OPP,但driver有可能覺得比較危險,不想使用,則可以調用dev_pm_opp_disable接口,禁止該OPP。這是後面很多查詢結構(除了dev_pm_opp_find_freq_exact)都無法查到該OPP。

相反,dev_pm_opp_enable用於使能指定的OPP。

注:調用dev_pm_opp_add添加進去的OPP,默認是enable的。

   1: int dev_pm_opp_get_opp_count(struct device *dev);
   2:  
   3: struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
   4:                                               unsigned long freq,
   5:                                               bool available);
   6:  
   7: struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
   8:                                               unsigned long *freq);
   9:  
  10: struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
  11:                                              unsigned long *freq);

OPP的查詢接口,返回相應的dev_pm_opp指針(當作一個句柄使用),包括:

dev_pm_opp_find_freq_floor,查詢小於或者等於指定freq的OPP,在返回OPP的同時,從freq指針中返回實際的freq值;

dev_pm_opp_find_freq_ceil,查詢大於或者等於指定freq的OPP,在返回OPP的同時,從freq指針中返回實際的freq值;

dev_pm_opp_find_freq_exact,精確查找指定freq的OPP,同時通過available變量,可以控制是否查找處於disable狀態的OPP。上面兩個查找接口,是不查找處於disable狀態的OPP的。

   1: unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
   2:  
   3: unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);

從指定的OPP句柄中,獲得頻率或者電壓值。

   1: #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
   2: int of_init_opp_table(struct device *dev);
   3: #else
   4: static inline int of_init_opp_table(struct device *dev)
   5: {
   6:         return -EINVAL;
   7: }
   8: #endif

從DTS中,解析並初始化一個設備的opp table。DTS的格式如下(參考arch/arm/boot/dts/omap34xx.dtsi):

cpus { 
        cpu@0 { 
                /* OMAP343x/OMAP35xx variants OPP1-5 */ 
                operating-points = < 
                        /* kHz    uV */ 
                        125000   975000 
                        250000  1075000 
                        500000  1200000 
                        550000  1270000 
                        600000  1350000 
                >; 
                clock-latency = <300000>; /* From legacy driver */ 
        }; 
};

以“operating-points”爲名稱,指定頻率和電壓組合,單位分別爲kHz和uV。具體解析過程不再描述。

發佈了35 篇原創文章 · 獲贊 46 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章