Linux pinctrl子系統分析之四 pinctrl device的註冊與註銷

  前面我們分析了pinctrl子系統相關的數據結構等內容,本章我們分析pinctrl device的註冊與註銷接口。

 

  針對pinctrl device的註冊與註銷主要涉及pinctrl_register、pinctrl_unregister、devm_pinctrl_register、devm_pinctrl_unregister這幾個接口。而devm_pinctrl_register、devm_pinctrl_unregister這兩個接口則主要由設備驅動模型實現資源申請與釋放,即使用者兩個接口,則pinctrl device無須在driver remove時進行資源的釋放(設備資源管理也是設備驅動子系統的一個模塊,該模塊實現資源的管理,也就是針對device申請的資源均存放到device的鏈表上,當對該device 進行destroy時,一併對這些資源進行釋放)。

 

Pinctrl device 註冊與註銷實現的功能

其實pinctrl device的註冊就是實現如下圖的數據結構間的關聯,這個我們之前也說了,理清了數據

結構間的關係,也就知道相應函數的實現流程了,尤其是linux內核的代碼,只要理解數據結構間的關係,那理解一個驅動模塊就事半功倍了。

 

pinctrl_register接口

針對pinctrl_register接口就是建立下圖的數據結構間的關聯圖,下面我們具體說明:

 

  1. 調用pinctrl_register進行pinctrl device的註冊時,需要傳遞struct pinctrl_desc類型的變量,該變量用於描述一個soc pin controller的信息,包含所支持的pin引腳的描述(每一個引腳的名稱與index)、pin複用操作的接口(主要是struct pinmux_ops類型的變量,包含引腳的申請與釋放接口、引腳複用設置接口、gpio引腳複用配置以及方向設置接口等)、pin引腳或group相關的引腳配置接口(包含引腳配置接口、引腳當前配置參數獲取接口、group相關引腳的配置接口、debug接口等)、group相關的操作接口(獲取group的個數、獲取group的名稱、獲取group對應的引腳內容、從設備樹設備節點中解析board pin描述信息並進行pinctrl map註冊的接口dt_node_to_map)
  2. 根據struct pinctrl_desc類型變量中的引腳描述成員pins、npins,對pin引腳進行解析,並針對每一個pin均創建一個對應的struct pin_desc類型的變量,並將其加入到基數樹pinctrl_dev->pin_desc_tree中,而struct pin_desc則主要描述該pin當前的配置信息(所屬function、group、pin引腳配置計數等,該數據結構在上一章已經介紹,當我們進行引腳複用配置調用pin_request時,則根據struct pin_desc類型變量記錄的值確定該引腳是否已經被別的模塊配置);
  3. 需要檢查pinctrl_desc定義的pinmux_ops、pinctrl_ops、pinconf_ops變量中各接口是否定義,做合法性檢測;
  4. 當完成以上操作後,即將該struct pinctrl_dev類型的變量添加到pinctrldev_list鏈表上,至此完成pinctrl device的註冊。

 

     pinctrl_register、devm_pinctrl_register主要實現soc pin controller描述相關信息的定義與註冊。該接口實現的功能也就是以上四點。

 

     pinctrl_register函數主要分爲pinctrl_init_controller、pinctrl_enable兩個函數,pinctrl_init_controller函數主要實現上述的1-3的內容,而pinctrl_enable則實現上述4的內容,主要將該pinctrl device添加到pinctrldev_list上。

       pinctrl_init_controller的實現如下所示,基本上也就實現上面的1-3點的內容,根據傳遞的struct pinctrl_desc類型的變量pctldesc,申請struct pinctrl_dev類型的內存,然後初始化pin_desc_tree、pin_group_tree、pin_function_tree(這三個基數樹變量主要存儲引腳配置的變量、group相關的變量、function相關的變量等信息,其中pin引腳加入到pin_desc_tree中的操作由pinctrl_register_pisn實現。而group、function加入到pin_group_tree、pin_function_tree這個操作是新內核加入的,因此這個加入操作沒有再pinctrl_register中,而是由具體的pinctrl device driver自行調用pinctrl_generic_add_group、pinmux_generic_add_function實現,在以後的內核升級中可能也會由pinctrl_register實現)

      而接口pinctrl_register_pins則根據該pinctrl device的引腳描述,將所有的引腳註冊進pinctrl device的pin_desc_tree中。該接口的實現如下,代碼邏輯也比較清晰,就不再細述。

 

pinctrl_unregister接口

該接口實現的功能剛好和pinctrl_register相反,此處就不細述。

 

Pinctrl device driver的實現流程

下面我們描述下如何實現pinctrl device driver,主要包含如下幾個步驟:

  1. 爲該soc pin controller 實現platform device driver驅動,然後在該驅動的probe接口中實現如下功能:
    1. 定義struct pinctrl_desc類型的變量,並實現相應的成員變量的配置,包含支持的引腳描述、支持的引腳複用接口的賦值、支持的引腳配置接口的賦值、支持的group操作接口以及dt2map接口的賦值等;
    2. 調用pinctrl_register/devm_pinctrl_register完成pinctrl device的註冊
    3. 定義該soc  pin controller的group相關變量的添加(若使用自行定義的結構存儲就自行實現,也可調用pinctrl_generic_add_group接口實現);
    4. 定義該soc  pin controller的function相關變量的添加(若使用自行定義的結構存儲就自行實現,也可調用pinctrl_generic_add_function接口實現);

 

        完成以上幾步,基本上就完成了pinctrl device driver的註冊。在本專欄的最後,我將實現一個虛擬的pinctrl device driver,並藉助sysfs進行調試,從而完成pinctrl 子系統的驅動開發實踐。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章