裝置驅動-【轉載】Pinctrl的配置與使用
版權宣告:本文為CSDN博主「spongebob1912」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/spongebob1912/article/details/109496964
簡述
soc內部管腳眾多,而多數管腳又可以配置成不同的功能,我們稱之為管腳複用;Linux引入pinctrl子系統,是為了統一各晶片廠商對這些管腳的管理跟配置。
通過調整pinctrl暫存器,我們可以配置一個或一組管教,配置項包括function、上拉下拉、驅動強度等,下面僅從使用者的角度介紹pinctrl在實踐中的應用。
應用例項
1.管腳定義
以高通平臺為例,在dts資料夾中我們會找到名為pinctrl的dtsi,裡面配置了幾乎所有用到的管腳,個別裡面沒有配置的管腳預設用作gpio,以下面一組管腳為例
- /* interrupt active */
- pmx_ts_int_active {
- ts_int_active: ts_int_active {
- mux {
- pins = "gpio65";
- function = "gpio";
- };
- config {
-
pins = "gpio65"
- drive-strength = <8>;
- bias-pull-up;
- };
- };
- };
- /* interrupt suspend */
- pmx_ts_int_suspend {
- ts_int_suspend: ts_int_suspend {
- mux {
- pins = "gpio65";
- function = "gpio";
- };
- config {
-
pins = "gpio65"
- drive-strength = <2>;
- bias-pull-down;
- };
- };
- };
裡面定義了一個管腳的兩種狀態,分別是active狀態管腳gpio65,function gpio內建上拉,強度為8;suspend狀態管腳gpio65,function gpio內建下拉,強度為2;
2.pinctrl state定義
為裝置新增自己的管腳定義,這個過程我們稱之為pinctrl state定義;
- pinctrl-names = "cyttsp_ts_active",
- "cyttsp_ts_suspend","cyttsp_ts_release";
- pinctrl-0 = <&ts_int_active &ts_reset_active>;
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- pinctrl-2 = <&ts_release>;
在dts中某個裝置的節點中新增如上引用,三個pinctrl name分別對應下面三個pinctrl-x,每個pinctrl-x我們稱之為一個pinctrl state,後續我們將在程式碼中通過name來找到相應的pinctrl state;
每組pinctrl state可以引用多個管腳定義。
3.pinctrl state切換
在完成管腳定義及pinctrl state定義之後,我們將在程式碼中獲取pinctrl state,並使用他們;
- struct pinctrl *ts_pinctrl;
- struct pinctrl_state *pinctrl_state;
- /* get pinctrl handle */
- ts_pinctrl = devm_pinctrl_get(dev);
- if (IS_ERR_OR_NULL(ts_pinctrl)) {
- rc = PTR_ERR(ts_pinctrl);
- dev_err(dev, "%s: Target does not use pinctrl %d\n", __func__, rc);
- return rc;
- }
- /* find pinctrl state by name */
- pinctrl_state = pinctrl_lookup_state(ts_pinctrl, PINCTRL_STATE_ACTIVE);
- if (IS_ERR_OR_NULL(pinctrl_state)) {
- rc = PTR_ERR(pinctrl_state);
- dev_err(dev, "%s: Can not lookup cyttsp_ts_active pinstate %d\n", __func__, rc);
- return rc;
- }
- /* select the pinctrl state */
- rc = pinctrl_select_state(ts_pinctrl, pinctrl_state);
- if (rc < 0)
- dev_err(dev, "%s: Cannot get active pinctrl state\n", __func__);
1.獲取pinctrl handler,每個裝置都會有自己的pinctrl handler,如果沒有,呼叫介面時將為它建立一個
原始碼參考/kernel/msm-3.18/drivers/pinctrl/core.c create_pinctrl();
2.得到pinctrl handler後,我們通過dts裡配置的pinctrl-name,找到相應的pinctrl state;
示例中找的是cyttsp_ts_active,對應dts裡的state為pinctrl-0,該state包含兩個管腳定義,分別是ts_int_active,ts_reset_active,具體定義到pinctrl dtsi裡面檢視;
3.找到相應的pinctrl state,只需呼叫pinctrl介面切換至該state即可,相應管腳即可切換為pinctrl dtsi中定義的狀態;
示例中將切換至ts_int_active狀態,相應的管腳gpio65將被配置為gpio,內建上拉,強度為8,其他管腳同理。
補充說明
在驅動跟裝置成功匹配後,驅動探測時將獲取該裝置名為default的pinctrl state,並切換至該state,這個過程中就會呼叫devm_pinctrl_get,獲取或建立pinctrl handler;
若相應dts節點沒有定義名為default的pinctrl state,則輸出日誌後返回,執行driver probe;
具體原始碼請參考/kernel/msm-3.18/drivers/base/dd.c really_probe()