日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
如何正確地使用Regulator

作者 | 趙青窕

審校 | 孫淑娟

Regulator幾乎是每一位驅(qū)動(dòng)開發(fā)者都會(huì)使用到的模塊,在處理過幾起與Regulator相關(guān)的bug后,我終于弄明白了。接下來(lái)我來(lái)分享下,到底該如何控制Regulator?

本文將從以下五個(gè)方面來(lái)闡述內(nèi)核中Regulator該如何控制:

  • 什么是Regulator
  • 設(shè)備樹配置
  • 核心API接口
  • 驅(qū)動(dòng)控制方法
  • 調(diào)試方法

(Lk和uefi階段的上電控制不屬于本文的范疇。)

1.什么是Regulator

一般來(lái)說,soc都會(huì)有配套的有限數(shù)量的pmu,而Regulator就是這個(gè)pmu的抽象,直白來(lái)說就是我們通過控制Regulator,進(jìn)而控制了pmu,從而達(dá)到對(duì)電的控制。

下圖是內(nèi)核中Regulator的整體框架圖,由三部分組成,分別提供了供其他驅(qū)動(dòng)使用的API接口和sysfs口,并可以控制硬件PMIC等這類器件的register,在本文中,將會(huì)介紹前兩部分。

2.設(shè)備樹配置

常用的設(shè)備樹配置主要涉及4個(gè)部分,共5個(gè)屬性,分別是配置對(duì)應(yīng)的Regulator,設(shè)備工作需要的電壓范圍,設(shè)置always-on屬性,設(shè)置boot-on屬性。

下面是一個(gè)典型的設(shè)備樹配置,供大家參考。

xxx {
test-avdd-supply = <&L5A>;
test-avdd-min-uv = <3000000>;
test-avdd-max-uv = <3000000>;
regulator-always-on;
regulator-boot-on;
}

test-avdd-supply

這個(gè)屬性是用來(lái)指明設(shè)備xxx使用的是哪一個(gè)Regulator,該屬性設(shè)置時(shí),需要先從原理圖中獲取對(duì)應(yīng)的供電信息,然后轉(zhuǎn)化到軟件上的標(biāo)識(shí)(通常原理圖中的標(biāo)識(shí)和平臺(tái)代碼dts中的相同,很容易識(shí)別到),從而配置該屬性;

test-avdd-min-uv和test-avdd-max-uv

這兩個(gè)屬性是用來(lái)指明該Regulator對(duì)應(yīng)的電壓范圍,這個(gè)范圍不能隨便設(shè)置,因?yàn)閜mu有它自身的驅(qū)動(dòng)能力范圍。驅(qū)動(dòng)能力的范圍可以通過以下方式獲取:

在平臺(tái)代碼的設(shè)備樹中查找,上面設(shè)備樹配置中,我采用了L5A,那我就在平臺(tái)的設(shè)備樹配置中找L5A的配置,如下樣例可以看出L5A的驅(qū)動(dòng)范圍是在1.65V到3.05V之間。

L5A: pmxxx_l5: regulator-l5 {
regulator-min-microvolt = <1650000>;
regulator-max-microvolt = <3050000>;
qcom,init-voltage = <2960000>;
status = “okay”;
}

我們雖然知道了驅(qū)動(dòng)能力范圍,但并不意味著我們就可以通過配置Regulator(后面會(huì)說明如何配置),設(shè)置這個(gè)范圍內(nèi)的任意電壓值。通過查看Regulator或者pmu的手冊(cè)都可以看出,每一個(gè)Regulator只能取這個(gè)范圍內(nèi)的離散值。

regulator-always-on

該屬性有兩個(gè)含義,第一層含義就是設(shè)置系統(tǒng)啟動(dòng)的時(shí)候,進(jìn)行相應(yīng)Regulator的上電操作,下圖基于MTK平臺(tái)的代碼就是對(duì)應(yīng)的上電操作。

第二層含義就是禁止對(duì)該Regulator進(jìn)行掉電的操作,如下圖的代碼所示,rdev->constraints->always_on在系統(tǒng)啟動(dòng)的時(shí)候會(huì)進(jìn)行設(shè)置,該變量代表了設(shè)備樹中是否設(shè)置了regulator-always-on屬性,當(dāng)設(shè)置該屬性時(shí),對(duì)應(yīng)的rdev->constraints->always_on = 1,則函數(shù)regulator_do_disable就不會(huì)執(zhí)行,從而該Regulator無(wú)法掉電。

regulator-boot-on

該屬性實(shí)際上同regulator-always-on屬性的第一個(gè)含義相同,但我個(gè)人建議在配置需要開機(jī)就上電的Regulator的時(shí)候,即使有regulator-always-on屬性,最好同時(shí)加上regulator-boot-on屬性,以防有些平臺(tái)regulator-always-on屬性沒有第一個(gè)含義的情況。

3.核心API接口

首先給大家介紹一下Regulator相關(guān)的API函數(shù)。

struct regulator *regulator_get(struct device *dev, const char *id)

該函數(shù)用來(lái)獲取對(duì)應(yīng)的Regulator,對(duì)應(yīng)到本文中的設(shè)備xxx,其函數(shù)調(diào)用方法時(shí)regulator_get(對(duì)應(yīng)xxx的struct device *dev,“test-avdd”),注意該函數(shù)中第2個(gè)參數(shù)是test-avdd,但設(shè)備樹中是test-avdd-supply,之所以設(shè)備樹和函數(shù)傳參不相同的原因是下圖中紅色方框標(biāo)注的代碼導(dǎo)致的。

int regulator_is_enabled(struct regulator *regulator)

該函數(shù)用來(lái)判斷對(duì)應(yīng)的regulator是否已經(jīng)enable。

當(dāng)返回0表示對(duì)應(yīng)Regulator處于disable狀態(tài)。

如果配置了always_on,該函數(shù)直接返回1,表示相應(yīng)的Regulator已經(jīng)enabled,否則會(huì)去讀取相應(yīng)的寄存器來(lái)獲取相應(yīng)Regulator的使能狀態(tài)寄存器。

該函數(shù)有著很重要的作用,但也是大家容易忽略的函數(shù),后面會(huì)給大家展示其重要性。

int regulator_set_volatage(struct regulator *regulator, int  min_uV,  int max_uV)

該函數(shù)中的第二個(gè)參數(shù)和第三個(gè)參數(shù)可以相同,也可以不同。當(dāng)不同的時(shí)候,就是設(shè)置的電壓范圍;當(dāng)相同的時(shí)候,就是設(shè)置的電壓值。

只有在設(shè)置值和當(dāng)前值不一樣,且設(shè)置的數(shù)據(jù)合理,才會(huì)進(jìn)行范圍設(shè)置。

  • 設(shè)置范圍

當(dāng)設(shè)置的范圍要超出該Regulator的驅(qū)動(dòng)能力范圍時(shí),且第三個(gè)參數(shù)大于第二個(gè)參數(shù),這種情況下,regulator_set_voltage會(huì)內(nèi)部把范圍縮小到該Regulator能驅(qū)動(dòng)的最大范圍。

同時(shí)用于將電壓設(shè)置為min_uV和max_uV范圍內(nèi),和min_uV最接近的電壓。

  • 設(shè)置值

如下面的代碼所示,其目的是對(duì)應(yīng)的電壓為2.8V,前面有介紹過,每一個(gè)Regulator只能取一定范圍內(nèi)的離散值,當(dāng)2.8V不屬于這些離散值中的任意值時(shí),就會(huì)設(shè)置失敗。

regulator_set_voltage(regulator, 2800000, 2800000)

int regulator_enable(struct regulator *regulator)

該函數(shù)用來(lái)enable對(duì)應(yīng)的Regulator,只有enable后,才能真正的供上電。

如果配置了always_on屬性,該函數(shù)直接返回0,其他情況下,需要根據(jù)實(shí)際情況來(lái)判斷,然后執(zhí)行相應(yīng)的操作,下圖是enable時(shí),具體的執(zhí)行函數(shù)。

從上圖可以看出,調(diào)用regulator_enable時(shí),只有在use_count為0的情況下才會(huì)做enable動(dòng)作,且use_count會(huì)自加1。use_count是比較重要的變量,在regulator_disable時(shí)也會(huì)用到,接下來(lái)我們就看以下regulator_disable。

int regulator_disable(struct regulator *regulator)

該函數(shù)用來(lái)disable對(duì)應(yīng)的Regulator。

如果配置了always_on屬性,該函數(shù)直接返回0。

regulator_disable函數(shù)內(nèi)部會(huì)調(diào)用_regulator_disable函數(shù),下圖是_regulator_disable的實(shí)現(xiàn)代碼,從圖中可以看出,當(dāng)use_count不為1時(shí),不會(huì)執(zhí)行disable動(dòng)作。

還有很多與Regulator相關(guān)的API函數(shù),如regulator_put,regulator_set_load等,但常用的就是上面的5個(gè)函數(shù)。

4. 驅(qū)動(dòng)控制方法

在驅(qū)動(dòng)中需要按照下面的步驟來(lái)執(zhí)行(針對(duì)一個(gè)Regulator只給一個(gè)設(shè)備供電的情況):

  • 通過regulator_get獲取對(duì)應(yīng)的Regulator
  • 通過regulator_set_voltage設(shè)置電壓
  • 通過regulator_is_enabled來(lái)判斷當(dāng)前Regulator的狀態(tài)
  • 根據(jù)上一步的結(jié)果,如果未enable,則調(diào)用 regulator_enable,否則不需要調(diào)用regulator_enable
  • regulator_disable

在實(shí)際工作中,我遇到過這樣的情景,沒有使用regulator_is_enabled進(jìn)行條件判斷,但無(wú)意中調(diào)用了兩次regulator_enable,這樣就會(huì)導(dǎo)致use_count = 2,在regulator_disable時(shí),由于use_count != 1,從而沒有進(jìn)行disable動(dòng)作,導(dǎo)致最后發(fā)現(xiàn)相應(yīng)的這路電無(wú)法掉電。

下面是一個(gè)簡(jiǎn)單的例子:

//step1: setting the regulator
rdev = regulator_get(dev, " test-avdd ");
regulator_set_voltage(rdev,28000000, 28000000);

//step2: judge enable or not and enable it
if (!regulator_is_enabled(rdev)) {
ret = regulator_enable(rdev);
if (ret != 0)
printk ("%s:regulator_enable fail, ret:%d\n",__func__, ret);
}

//step3: disable regulator
if (regulator_is_enabled(rdev)) {
ret = regulator_disable(rdev);
if (ret != 0)
printk("%s:regulator_disable fail, ret:%d\n",__func__, ret);
}
}

還有一個(gè)驅(qū)動(dòng)是在收到應(yīng)用層的命令后,才進(jìn)行regulator的enable或者disable的情況下,建議使用regulator_is_enable來(lái)進(jìn)行判斷,這樣就可以有效避免上層多次發(fā)送enable命令導(dǎo)致use_count增加的情況。

當(dāng)某一個(gè)Regulator給多個(gè)設(shè)備供電時(shí),需要考慮多個(gè)設(shè)備的情況,就不建議使用regulator_is_enabled,因此多設(shè)備通過一路Regulator控制時(shí),會(huì)比較復(fù)雜,比如設(shè)備A已經(jīng)enable了某一路Regulator,某一時(shí)刻設(shè)備B也需要enable,但由于通過regulator_is_enabled發(fā)現(xiàn)已經(jīng)enable時(shí),從而不進(jìn)行enable操作,但之后的某一時(shí)刻,設(shè)備A需要進(jìn)行掉電操作,因?yàn)橹皉egulator_enable只調(diào)用了一次,那use_count = 1,那此時(shí)設(shè)備A就可以regulator_disable成功,但這個(gè)時(shí)候設(shè)備B不希望掉電,但設(shè)備A把電掉了,導(dǎo)致設(shè)備B就異常了,因此同一路電給多個(gè)設(shè)備供電時(shí),不建議使用regulator_is_enable。針對(duì)多種設(shè)備,最簡(jiǎn)單的處理方式就是使用regulator-always-on屬性。

5.調(diào)試方法

此處我主要給大家介紹下sys節(jié)點(diǎn)的調(diào)試方式。節(jié)點(diǎn)的路徑是/sys/kernel/debug/regulator/,在這個(gè)路徑下面,大家會(huì)看到很多Regulator,如下圖所示:

從上圖我們可以看出,根據(jù)名稱就可以找到我們需要的Regulator,比如從原理圖中看出來(lái)我們使用的是ldoe9,那么就可以進(jìn)入路徑/sys/kernel/debug/regulator/18200000.rsc:rpmh-regulator-ldoe9-pm6150a_l9,在該路徑下可以查看對(duì)應(yīng)的open_count(cat open_count)或者進(jìn)行enable或者disable控制(實(shí)際上就是echo 1或者0到對(duì)應(yīng)的節(jié)點(diǎn)即可)。

至此,Regulator的使用以及調(diào)試就給大家介紹完了,上面的介紹比較簡(jiǎn)單,屬于入門級(jí)別的內(nèi)容,但這些內(nèi)容已經(jīng)足夠大部分驅(qū)動(dòng)的使用進(jìn)行調(diào)試了,希望大家都能通過這篇文章,真正了解到Regulator該如何使用。

作者介紹

趙青窕,社區(qū)編輯,從事多年驅(qū)動(dòng)開發(fā)。


網(wǎng)站題目:如何正確地使用Regulator
本文鏈接:http://www.dlmjj.cn/article/dhhchjg.html