pinctrl介紹文檔:
內核目錄\Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
首先介紹幾個概念:
Bank: 以引腳名爲依據, 這些引腳分爲若干組, 每組稱爲一個Bank
比如s3c2440裏有GPA、GPB、GPC等Bank。
每個Bank中有若干個引腳, 比如GPA0,GPA1, ..., GPC0, GPC1,...等引腳
Group: 以功能爲依據, 具有相同功能的引腳稱爲一個Group
比如s3c2440中串口0的TxD、RxD引腳使用 GPH2,GPH3, 那這2個引腳可以列爲一組
比如s3c2440中串口0的流量控制引腳使用 GPH0,GPH1, 那這2個引腳也可以列爲一組
State: 設備的某種狀態, 比如內核自己定義的"default","init","idel","sleep"狀態;
也可以是其他自己定義的狀態, 比如串口的"flow_ctrl"狀態(使用流量控制)
每種狀態會對應一組或多組group。
可以通過函數設置設備狀態。
a. 設備樹中pinctrl節點:
a.1 它定義了各種 pin bank, 比如s3c2440有GPA,GPB,GPC,...,GPB各種BANK, 每個BANK中有若干引腳:
pinctrl_0: pinctrl@56000000 {
reg = <0x56000000 0x1000>;
gpa: gpa {
gpio-controller; //表示是一個bank
#gpio-cells = <2>; /* 使用gpa bank中的引腳時, 需要2個u32來指定引腳 */
};
gpb: gpb {
gpio-controller;
#gpio-cells = <2>;
};
gpc: gpc {
gpio-controller;
#gpio-cells = <2>;
};
gpd: gpd {
gpio-controller;
#gpio-cells = <2>;
};
};
a.2 它還定義了各種group(組合), 某種功能所涉及的引腳稱爲group,
pin groups是pinctrl下面的子節點
比如串口0要用到2個引腳: gph0, gph1:
uart0_data: uart0-data {
/* 在GPHCON寄存器中gph0,gph1可以設置以下值:
0 --- 輸入功能
1 --- 輸出功能
2 --- 串口功能
我們要使用串口功能,samsung,pin-function 設置爲2
*/
samsung,pins = "gph-0", "gph-1"; //用哪些引腳實現這個功能
samsung,pin-function = <2>;//使用這個功能需要將寄存器設置成什麼值
};
uart0_sleep: uart0_sleep {
/* 在GPHCON寄存器中gph0,gph1可以設置以下值:
0 --- 輸入功能
1 --- 輸出功能
2 --- 串口功能
我們要使用輸入功能,samsung,pin-function 設置爲0
*/
samsung,pins = "gph-0", "gph-1";
samsung,pin-function = <0>;
};
samsung-pinctrl.txt中也定義了一下幾種屬性的用法:
- samsung,pin-val: Initial value of pin output buffer.
- samsung,pin-pud: Pull up/down configuration.
- samsung,pin-drv: Drive strength configuration.
- samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
- samsung,pin-drv-pdn: Drive strength configuration in power down mode.
b. 設備節點中要使用某一個 pin group:
serial@50000000 {
......
pinctrl-names = "default", "sleep"; /* 既是名字, 也稱爲state(狀態) */
pinctrl-0 = <&uart0_data>;
pinctrl-1 = <&uart0_sleep>;
};
pinctrl-names中定義了2種state: default 和 sleep,
default 對應的引腳是: pinctrl-0, 它指定了使用哪些pin group: uart0_data
sleep 對應的引腳是: pinctrl-1, 它指定了使用哪些pin group: uart0_sleep
c. platform_device, platform_driver匹配時對pinctrl的處理:
platform_device和platform_driver的匹配完成後,最終都會調用到 really_probe()函數 (drivers/base/dd.c)
really_probe:
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
dev->pins->default_state = pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_DEFAULT); /* 獲得"default"狀態的pinctrl */
dev->pins->init_state = pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_INIT); /* 獲得"init"狀態的pinctrl */
ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state); /* 優先設置"init"狀態的引腳 */
ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state); /* 如果沒有init狀態, 則設置"default"狀態的引腳 */
......
ret = drv->probe(dev);
如果設備節點中指定了pinctrl, 在對應的probe函數被調用之前, 先"bind pins", 即先綁定、設置引腳狀態。
d. 在驅動程序中設置引腳狀態:
devm_pinctrl_get_select_default(struct device *dev); // 將引腳設置爲"default"狀態
// 根據name將引腳設置爲某種狀態 比如default,sleep
pinctrl_get_select(struct device *dev, const char *name);
pinctrl_put(struct pinctrl *p); // 不再使用, 退出時調用