1. 程式人生 > >高通驅動樹詳解

高通驅動樹詳解

補充:Drive Strength && tri-state相關概念

{

Drive Strength(也被稱為:driving strength),表示“驅動強度”。這個引數用來控制訊號強度,數值越大代表訊號強度越高。

tri-state:三態,高電平、低電平、高阻。

實質

電路分析時高阻態可做開路理解。你可以把它看作輸出(輸入)電阻非常大。它的極限狀態可以認為懸空(開路)。也就是說理論上高阻態不是懸空,它是對地或對電源電阻極大的狀態。而實際應用上與引腳的懸空幾乎是一樣的。

意義

當閘電路的輸出上拉管導通而下拉管截止時,輸出為高電平;反之就是低電平;如上拉管和下拉管都截止時,輸出端就相當於浮空(沒有電流流動),其電平隨外部電平高低而定,即該閘電路放棄對輸出端電路的控制 。

表示方法

高阻態常用字母 Z 表示。

原有GPIO配置框架:
之前所有的gpio操作都是通過gpiolib來實現,常用的api包括:
staticinline int gpio_request(unsigned gpio, const char *label);
staticinline int gpio_direction_input(unsigned gpio);
staticinline int gpio_direction_output(unsigned gpio, int value);
staticinline void gpio_set_value(unsigned gpio, int value);
staticinline void gpio_free(unsigned gpio);
在硬體設計確定了某個裝置需要使用哪些gpio之後,軟體需要做的是(以msm8916平臺tp的中斷為例):
1)在msm8916-cdp.dsi中定義使用哪個gpio


[email protected]{
[email protected]{
compatible= "goodix,gt9xx";
reg= <0x5d>;
interrupt-parent= <&msmgpio>;
interrupts= <13 0x2>;
interrupt-gpios= <&msm_gpio 13 0x00>;
};
}
2)在board-8916-gpiomux.c中定義gpio的suspend和active狀態
staticstruct gpiomux_setting atmel_int_act_cfg
 = {
.func =GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_UP,
};
staticstruct gpiomux_setting atmel_int_sus_cfg = {
.func =GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
.pull =GPIOMUX_PULL_NONE,
};
staticstruct msm_gpiomux_config msm_touch_configs[] __initdata = {
.gpio = 13,
.settings = {
[GPIOMUX_ACTIVE] =&atmel_int_act_cfg,
[GPIOMUX_SUSPENDED]= &atmel_int_sus_cfg,
},
},
PinControl 框架
Gpiolib方式的缺點在於:當同一套程式碼對應多個board設計時,需要在board--gpiomux.c檔案中加巨集進行區分。如在同一個分支上支援3個專案,在board-msm8974-gpiomux.c檔案中添加了很多巨集控。
pinctrl方式可以避免程式碼中的這種冗餘程式碼,它將board--gpiomux.c檔案中的配置資訊移到-pinctrl.dtsi;這樣,針對不同project的board設計,分別在各自project的-pinctrl.dtsi中定義各自的gpio配置資訊。
Pinctrlsubsystem 分為3部分:Pinctrl core、Pinmux和Pinconf。
pinctrlcore是pincontrol子系統的核心,提供了和devicedriver互動的API;
pinmux用於實現pin的複用;
pinconf用於實現pin的配置,如輸入/輸出、pulldown/pull up、driverstrength等;另外還提供了用於debug的介面。
與gpio子系統的互動
雖然pinctrl提供了pinctrl_request_gpio()這樣的API,但在程式碼中不可以直接呼叫pinctrl_request_gpio(),在該函式的定義處也有說明,如下:
“*This function should *ONLY* be used from gpiolib-based GPIO drivers,
*as part of their gpio_request() semantics, platforms and individualdrivers
*shall *NOT* request GPIO pins to be muxed in.”
當裝置驅動申請一個gpio時,仍然需要呼叫gpio_request(),這裡會呼叫pinctrl_request_gpio()。呼叫過程如下:
gpio_request()
gpiod_request()
chip->request(chip,gpio_chip_hwgpio(desc));
在pinctrl_msm.c中,重新定義了chip->request()。
msm_pinctrl_probe()
msm_register_gpiochip()
gc->request= msm_pinctrl_request_gpio;
這裡msm_pinctrl_request_gpio()會調pinctrl_request_gpio();
同樣地,對於pinctrl_free_gpio()、pinctrl_gpio_direction_input()和pinctrl_gpio_direction_output()也有類似說明。
因此在clientdevice驅動中,申請和釋放gpio仍然要調gpio_request()、gpio_free();設定gpio為input/output仍然要調gpio_direction_input()和gpio_direction_output()。
Pinctrl註冊
全文以msm8916平臺為例進行分析。
當tlmm載入時,msm_tlmm_v4_probe()最後會調msm_pinctrl_probe(),其中會將pinctrl.dtsi中定義的pinctrlinfo解析出來,並且重新定義chip->request()、chip->free()等函式。
具體的呼叫關係如下圖所示:
postcore_initcall(msm_tlmm_v4_drv_register); //Pinctrl-msm-tlmm-v4.c
msm_tlmm_v4_probe //匹配pinctrl.dtsi定義的compatible
msm_pinctrl_probe //pinctrl_msm.c
msm_pinctrl_get_drvdata(dd,pdev); //解析pinctrl.dtsi,儲存到dd
msm_pinctrl_dt_parse_pintype(node,dd);
msm_pinctrl_dt_parse_pins(node,dd);
msm_register_gpiochip(dd); //定義gpio_request()、gpio_free()
gc->request= msm_pinctrl_request_gpio;
gc->free= msm_pinctrl_free_gpio;
msm_register_pinctrl(dd);
dd->pctl_dev= pinctrl_register(ctrl_desc, dd->dev, dd);
Pinstates
一個pinstate對應對pin腳的一種配置,一個pin腳可以配置多個狀態,對狀態的個數也沒有限制。
state的定義和電源管理關係比較緊密,例如當裝置active的時候,我們需要pincontroller將相關的一組pin設定為具體的裝置功能,而當裝置進入sleep狀態的時候,需要pincontroller將相關的一組pin設定為普通GPIO,並精確的控制GPIO狀態以便節省系統的功耗。
Pinctrl-state.h中給出了常用的3種狀態:
    default
default狀態表示裝置處於active時的狀態,一般在裝置驅動的.resume中配置,另外在啟動時也會配置pin腳為default狀態。
    idle
idle狀態表示系統處於idle時需要配置的pin腳狀態,此時系統並沒有進入深度休眠。
    sleep
sleep狀態表示系統處於深度休眠時的pin腳狀態,一般在裝置驅動的.suspend中配置。
當然我們也可以定義任意形式的state,如“on”、“off”等。
[email protected]{
compatible= "goodix,gt9xx";
reg= <0x5d>;
pinctrl-names= "gt9xx_int_active", "gt9xx_int_suspend";
pinctrl-0= <&gt9xx_int_active>;
pinctrl-1= <&gt9xx_int_sleep>;
interrupt-parent= <&msm_gpio>;
interrupts= <13 0x2>;
……
}
pinctrl-names定義了clientdevice用到的state列表。state有兩種標識,一種就是pinctrl-names定義的字串列表,另外一種就是ID。ID從0開始,依次加一。根據例子中的定義,stateID等於0(名字是"gt9xx_int_active")的state對應pinctrl-0屬性,stateID等於1(名字是"gt9xx_int_suspend")的state對應pinctrl-1屬性。
pinctrl-x是一個控制代碼(phandle)列表,每個控制代碼指向一個pinconfiguration。
Boot時配置default狀態
如果pin只定義了default狀態,那麼在裝置驅動中不需要再對該pin作處理,因為在啟動時會自動設為default狀態。
在載入驅動模組時,如果驅動和裝置匹配,最終就會調到driver定義的probe函式。在這個過程中,如果使能了pinctrl,而且定義了pin的default狀態,就會配置pin腳為該狀態。
具體程式碼流程如下:
driver_probe_device(structdevice_driver *drv, struct device *dev)
really_probe(dev,drv);
pinctrl_bind_pins(dev);
if(dev->bus->probe) {
ret= dev->bus->probe(dev);
}else if (drv->probe) {
ret= drv->probe(dev);
}
pinctrl_bind_pins(dev)的呼叫過程如下:
pinctrl_bind_pins(dev);
dev->pins->p= devm_pinctrl_get(dev);
dev->pins->default_state= pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_DEFAULT);
pinctrl_select_state(dev->pins->p,dev->pins->default_state);
對於不使用pinctrl的平臺,pinctrl_bind_pins(dev)直接返回0;
Pingroups
SOC上需要同時配置一組gpio來支援某些功能,如I2C、SPI、UART、SDC等,在-pinctrl.dtsi中將這些pin定義為一個group。
配置統一的情況
一組gpio在各個狀態下的配置都相同,這種配置比較常見也比較簡單。如i2c,在active和suspend狀態下,SDA和SCL的配置都相同:active狀態下都是配置為8mA上拉,suspend狀態下都配置為2mA和nopull。
首先在msm8916_pinctrl.c中定義suspend和active狀態下的pin腳配置資訊,如下:
pmx_i2c_0{

qcom,pins= <&gp 7>, <&gp 6>; //使用gpio_6和gpio_7
qcom,num-grp-pins= <2>; //共兩個gpio
qcom,pin-func= <3>; //複用功能為i2c
label= "pmx_i2c_0"; //表示同一組
i2c_0_active:i2c_0_active {
drive-strength= <8>;
bias-pull-up;
};
i2c_0_sleep:i2c_0_sleep {
drive-strength= <2>;
bias-disable;
};
};
然後在msm8916.dtsi中增加pinctrlinfo的引用:
i2c_0:[email protected] {
compatible= "qcom,i2c-msm-v2";
reg-names= "qup_phys_addr", "bam_phys_addr";
reg= <0x78b6000 0x600>,
<0x7884000 0x23000>;
interrupt-names= "qup_irq", "bam_irq";
interrupts= <0 96 0>, <0 238 0>;
clocks= <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>;
clock-names= "iface_clk", "core_clk";
qcom,clk-freq-out= <100000>;
qcom,clk-freq-in = <19200000>;
pinctrl-names= "i2c_active", "i2c_sleep";
pinctrl-0= <&i2c_0_active>;
pinctrl-1= <&i2c_0_sleep>;
qcom,master-id= <86>;
};
配置不統一的情況
如SDC,每個pin腳的active和sleep狀態配置各不相同,需要分開設定。
1)在msm8916_pinctrl.c中分別定義各個pin的suspend和active狀態下的配置資訊,如下:

sdc:sdc {
qcom,pin-type-sdc;

qcom,num-pins= <6>;



#qcom,pin-cells= <1>;
};
pmx_sdc1_clk{
qcom,pins= <&sdc 0>;
qcom,num-grp-pins= <1>;
label= "sdc1-clk";
sdc1_clk_on:clk_on {
bias-disable;
drive-strength= <16>;
};
sdc1_clk_off:clk_off {
bias-disable;
drive-strength= <2>;
};
};
pmx_sdc1_cmd{
qcom,pins= <&sdc 1>;
qcom,num-grp-pins= <1>;
label= "sdc1-cmd";
sdc1_cmd_on:cmd_on {
bias-pull-up;
drive-strength= <10>;
};
sdc1_cmd_off:cmd_off {
bias-pull-up;
drive-strength= <2>;
};
};
pmx_sdc1_data{
qcom,pins= <&sdc 2>;
qcom,num-grp-pins= <1>;
label= "sdc1-data";
sdc1_data_on:data_on {
bias-pull-up;
drive-strength= <10>;
};
sdc1_data_off:data_off {
bias-pull-up;
drive-strength= <2>;
};
};
2)msm8916-cdp.dtsi中作出相應修改:
&sdhc_1{
vdd-supply= <&pm8916_l8>;
qcom,vdd-voltage-level= <2900000 2900000>;
qcom,vdd-current-level= <200 400000>;
vdd-io-supply= <&pm8916_l5>;
qcom,vdd-io-always-on;
qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level= <1800000 1800000>;
qcom,vdd-io-current-level= <200 60000>;
//qcom,pad-pull-on= <0x0 0x3 0x3>;
//qcom,pad-pull-off= <0x0 0x3 0x3>;
//qcom,pad-drv-on= <0x4 0x4 0x4>;
//qcom,pad-drv-off= <0x0 0x0 0x0>;
pinctrl-names= "active", "sleep";
pinctrl-0= <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
pinctrl-1= <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
qcom,nonremovable;
status= "ok";
};
對sdhc_2也是同樣的配置。
另外還有一種情況,對於一組gpio,在不同state下pin_func定義不同的情況,如wifi,在active狀態設定為wifi功能,在suspend狀態下設定為普通gpio。
[email protected]{
...
pmx-wcnss-5wire-active{
qcom,pins= <&gp 40>, <&gp 41>, <&gp 42>, <&gp43>.
<&gp44>;
qcom,pin-func= <1>;
qcom,num-grp-pins= <5>;
label= "wcnss-5wire-active";
wcnss-5wire-active:wcnss-active {
drive-strength= <6>; / * 6MA */
bias-pull-up;
};
};
pmx-wcnss-5wire-suspend{
qcom,pins= <&gp 40>, <&gp 41>, <&gp 42>, <&gp43>.
<&gp44>;
qcom,pin-func= <0>;
qcom,num-grp-pins= <5>;
label= "wcnss-5wire-suspend";
wcnss-5wire-sleep:wcnss-sleep {
drive-strength= <6>; / * 6MA */
bias-pull-down;
};
};
};
PinctrlAPI
structpinctrl *devm_pinctrl_get(struct device *dev);
獲取該device對應的pinctrlhandler。
structpinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char*name);
查詢name指定的pinctrlstate。
intpinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);
配置pin腳為指定的state。
Usecase
下面舉例配置tp的中斷腳。
1)在msm8916-pinctrl.dtsi中定義pinctrlinfo:
&soc{
tlmm_pinmux:[email protected]
gt9xx_int_pin{
qcom,pins= <&gp 13>;
qcom,num-grp-pins= <1>;
qcom,pin-func= <0>;
label= "gt9xx_int_pin";

gt9xx_int_active:active {
drive-strength= <2>;    
bias-pull-up;
};

gt9xx_int_sleep:sleep {
drive-strength= <2>;
bias-disable;
};
};
}
2)在msm8916-cdp.dtsi中tp的節點中新增引用:
[email protected]{
compatible= "goodix,gt9xx";
reg= <0x5d>;
pinctrl-names= "gt9xx_int_active", "gt9xx_int_suspend";
pinctrl-0= <&gt9xx_int_active>;
pinctrl-1= <&gt9xx_int_sleep>;
interrupt-parent= <&msm_gpio>;
interrupts= <13 0x2>;
……
}
3)在tp驅動中新增配置。
a.定義pinctrl_info:
#defineGOODIX_PINCTRL_STATE_SLEEP "gt9xx_int_suspend"
#defineGOODIX_PINCTRL_STATE_DEFAULT "gt9xx_int_active"
structgtp_pinctrl_info{
structpinctrl *pinctrl;
structpinctrl_state *gpio_state_active;
structpinctrl_state *gpio_state_suspend;
};
staticstruct gtp_pinctrl_info gt9xx_pctrl;
staticint gtp_pinctrl_init(struct device *dev)
{
gt9xx_pctrl.pinctrl= devm_pinctrl_get(dev);
if(IS_ERR_OR_NULL(gt9xx_pctrl.pinctrl)) {
pr_err("%s:%dGetting pinctrl handle failed\n",
__func__,__LINE__);
return-EINVAL;
}
gt9xx_pctrl.gpio_state_active= pinctrl_lookup_state(
gt9xx_pctrl.pinctrl,
GOODIX_PINCTRL_STATE_DEFAULT);
if(IS_ERR_OR_NULL(gt9xx_pctrl.gpio_state_active)) {
pr_err("%s:�ailed to get the active state pinctrl handle\n",
__func__,__LINE__);
return-EINVAL;
}
gt9xx_pctrl.gpio_state_suspend= pinctrl_lookup_state(
gt9xx_pctrl.pinctrl,
GOODIX_PINCTRL_STATE_SLEEP);
if(IS_ERR_OR_NULL(gt9xx_pctrl.gpio_state_suspend)) {
pr_err("%s:�ailed to get the suspend state pinctrl handle\n",
__func__,__LINE__);
return-EINVAL;
}
return0;
}
b.在probe函式中初始化pinctrl_info,並設定state:
staticint goodix_ts_probe(struct i2c_client *client, const structi2c_device_id *id)
{
goodix_parse_dt(&client->dev,pdata);
gtp_request_io_port(ts);
gtp_pinctrl_init(&ts->client->dev);
pinctrl_select_state(gt9xx_pctrl.pinctrl,gt9xx_pctrl.gpio_state_active);
……
}
c.在suspend()和resume()中分別設定為activestate和suspendstate:
staticint goodix_ts_suspend(struct device *dev)
{
structgoodix_ts_data *ts = dev_get_drvdata(dev);
intret = 0, i;
ret= pinctrl_select_state(gt9xx_pctrl.pinctrl,
gt9xx_pctrl.gpio_state_suspend);
if(ret)
pr_err("%s:�annot set pin to suspend state",
__func__,__LINE__);
……
if(ts->use_irq)
gtp_irq_disable(ts);
……
returnret;
}
staticint goodix_ts_resume(struct device *dev)
{
structgoodix_ts_data *ts = dev_get_drvdata(dev);
intret = 0;
ret= pinctrl_select_state(gt9xx_pctrl.pinctrl,
gt9xx_pctrl.gpio_state_active);
if(ret)
pr_err("%s:�annot set pin to suspend state",
__func__,__LINE__);
……
if(ts->use_irq)
gtp_irq_enable(ts);
……
returnret;
}

相關推薦

驅動

補充:Drive Strength && tri-state相關概念 { Drive Strength(也被稱為:driving strength),表示“驅動強度”。這個引數用來控制訊號強度,數值越大代表訊號強度越高。 tri-state:三態,高

平臺msm8953 Linux DTS(Device Tree Source)裝置之二(DTS裝置匹配過程)

本系列導航:有上一篇文章,我們瞭解了dts的背景知識和相關基礎,這次我們對應實際裝置進行一下相關分析。DTS裝置樹的匹配過程一個dts檔案確定一個專案,多個專案可以包含同一個dtsi檔案。找到該專案對應的dts檔案即找到了該裝置樹的根節點。kernel\arch\arm\bo

linux裝置驅動uevent平臺battery上報電量例項

本文以高通平臺上的android系統為參照展開探討。1,uevent是什麼呢? uevent是一種linux裝置模型中的一個組成部分。kset中包含的uevent_ops結構體擁有uevent的操作函式。 uevent可以在裝置發生變化時主動通知應用層。是對普通先註冊裝置後

分享《Linux裝置驅動開發》第2版清電子版

新浪微博:@宋寶華Barry 在@微盤 分享了《linux裝置驅動開發詳解》第2版1080P電子版,擬升級為第3版,3.16核心,Cortex-A9 SMP,Device tree, DVFS, suspend/hibernation, big.LITTLE, CMA,分層/

《Linux4.0裝置驅動開發》筆記--第十八章:ARM Linux裝置

18.1 ARM裝置樹簡介 裝置舒適一種描述印鑑的資料結構,它起源於OpenFirmware(OF) 採用裝置樹前後對比: 採用裝置樹之前:ARM架構的板極硬體細節過多的被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx中

並發流量網站架構

高並發高流量網站架構詳解(推薦)高並發高流量網站架構詳解Web2.0的興起,掀起了互聯網新一輪的網絡創業大潮。以用戶為導 向的新網站建設概念,細分了網站功能和用戶群,不僅成功的造就了一大批新生的網站,也極大的方便了上網的人們。但Web2.0以用戶為導向的理念,使得新 生的網站有了新的特點——高並發,高流量,數

線段

延遲 操作 void space i++ 排序 string ++ 處理 #include"stdio.h"#include"cstdio"#include"algorithm"#include"string.h"using namespace std;/*********

泛型配符

object 指向 string類型 類型參數 tlist i++ 泛型 通配符 如果 一、基本概念:在學習Java泛型的過程中, 通配符是較難理解的一部分. 主要有以下三類:1. 無邊界的通配符(Unbounded Wildcards), 就是<?>, 比如L

HTTP協議報文、工作原理及Java中的HTTP信技術

tor 報文 buffered mod protoc 禁止 ans 請求報文 客戶端 博客園 首頁 新隨筆 聯系 管理 訂閱

Gin 路由解析

pos ima gpo image 中大 class 沒有 gin clas 說明: 無意間看到gin 中有trees的屬性,好奇想一探究竟,到底gin是怎樣生成路由解析樹的? 這是一個測試截圖,圖中大概可以了解到gin是怎樣做路由解析的。配合源碼的閱讀,解析樹大致如下:

回文

out 圖片 tchar isp name algorithm Go AI ans 無。 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#inc

李超

ref query math sca www. size double 是個 main 李超樹是個什麽東西呢? 其實就是一棵線段樹。。。。 我們來看這一道題 其實就是這樣一道題目 在二維空間中插入一條直線,詢問x=k的地方最上面一條直線的編號 李超樹儲存的是

USB虛擬邏輯分析儀,虛擬邏輯分析儀級觸發功能及圖示

ces jpg 高級 應用 shadow bcf ext ado 很多 LA2132 、32\64通道 G系列USB虛擬邏輯分析儀有很多高級觸發功能,但許多用戶用不好這些觸發功能,下面介紹這些功能的使用。 時序測量: 采集的數據作為時序顯示。 LVDS簡介 :LVDS即低壓

線段(單點更新與成段更新\區間更新操作)

      本文純屬原創,轉載請註明出處,謝謝。         距離第一次接觸線段樹已經一年多了,再次參加ACM暑假集訓,這一次輪到我們這些老傢伙們給學弟學妹們講解線段樹了,所以就自己重新把自己做過的題目看

左偏

引入 左偏樹也叫可並堆。 堆想必大家是很熟悉的了,手寫可能沒有過,但用絕對用過,priority_queue就是STL中的一個二叉堆。 priority_queue和手寫的二叉堆差不多,使用起來很方便,平均的時間複雜度都是在O(logN)。 但是一旦要求合併兩個堆,我們的priority_q

Flume NG可用叢集搭建(基於flume-1.7.0)

1、Flume NG簡述 Flume NG是一個分散式,高可用,可靠的系統,它能將不同的海量資料收集,移動並存儲到一個數據儲存系統中。輕量,配置簡單,適用於各種日誌收集,並支援 Failover和負載均衡。並且它擁有非常豐富的元件。Flume NG採用的是三層架構:Agent層,Collecto

什麽是透明、匿名、匿代理?

mar 因此 過程 51cto 大量 .com 數據 示例 應用 隨著大數據的應用越來越廣泛,應用的行業也越來越多,我們每日都可以看到大數據的一些新穎的應用,從而幫助人們從中獲取到真正有用的價值,隨著很多工作的開展,我們需要大量的IP操作,這時為了避免IP被封,使用代理IP

GMM混合斯模型演算法

使用概率模型的原因 k均值等價於假設了球對稱形狀的聚類。使用帶權歐式距離,仍然假設了軸對齊的橢球。沒有考慮聚類的形狀。 促使概率模型的原因:混合模型 提供觀測點到聚類的軟分配soft assignment(分配包含不確定性) 考慮了聚類的形狀而不僅僅是中心

Linux裝置驅動開發 第3版 (即 Linux裝置驅動開發 基於最新的Linux 4 0核心 )進展同步更

                本博實時更新《Linux裝置驅動開發詳解(第3版)》的最新進展。 目前已經完成稿件。 2015

MPT

目錄 MPT樹定義 MPT樹的作用是什麼? 字首樹與默克爾樹 字首樹 默克爾樹 三種節點型別 MPT中的Merkle HP編碼 官方表示形式 相關MPT樹 參考目錄 @ MP