目錄
- 一、簡單介紹
- 二、主要源碼文件和目錄
- gpio子系統
- pinctrl子系統
- 兩個子系統之間的關系
- 設備樹例子
- 三、主要的數據結構
- gpio子系統
- pinctrl子系統
- 四、驅動初始化流程
- 五、難點說明
一、簡單介紹
GPIO子系統: Linux GPIO子系統是Linux內核中負責處理GPIO(通用輸入輸出)的一部分。它提供了一套接口,使得硬件工程師和軟件開發者能夠方便地使用和控制GPIO(來自百度百科);
Linux的pinctrl子系統是一種提供引腳復用和引腳配置的機制,它允許內核或者用戶空間動態地控制硬件的引腳功能(來自百度百科);
二、主要源碼文件和目錄
gpio子系統
目錄 linux-5.10.1xx/drivers/gpio/ ;
gpio-dwapb.c : 以DesignWare的IP庫為例,具體芯片平臺架構gpio外設的適配文件,其它平臺gpio-xxxx.c 同理;
gpiolib-devres.c: 主要關于struct gpio_desc結構的操作;
gpiolib.c : gpio子系統和核心層;
gpiolib-sysfs.c : 在用戶空間通過sysfs文件系統導出引腳,操作引腳的底層實現函數;
gpiolib-cdev.c : struct gpio_device結構注冊為字符設備,操作相關函數;
gpiolib-legacy.c : 幾個操作函數;
gpiolib-of.c : 關于gpio設備樹配置解析的操作函數封裝;
gpio-mmio.c : struct gpio_chip的鉤子函數的定義在此處;
文件整體調用關系圖:
pinctrl子系統
目錄 linux-5.10.xxx/drivers/pinctrl/;
core.c:pinctrl核心,向外暴露的接口可以鏈接其它文件中的調用流程轉換;
devicetree.c : 解析某個設備的設備樹中關于引腳的設置,如解析pinctrl-0屬性;
pinconf-generic.c: 操作設備樹節點到 struct pinctrl_map結構的函數封裝和pinctrl-utils.c 中接口配合使用;
pinconf.c : 操作struct pinctrl_map 和 struct pinctrl_setting的輔助接口;
pinctrl-xxxxx.c:具體芯片平臺解析設備樹pinctrl外設的probe函數,自定義結構的定義包含struct pinctrl_dev 是它的派生類;
pinctrl-utils.c :struct pinctrl_map 結構成員的操作;
pinmux.c: 請求pin引腳為某種復用功能時的函數集合,向下調用struct pinmux_ops *ops->set_mux成員函數,具體將配置進行執行到寄存器的操作實現;
文件整體調用關系圖:
兩個子系統之間的關系
核心紐帶數據結構:
//此結構定義的是gpio空間和pinctrl空間一段對應的引腳范圍
struct pinctrl_gpio_range{struct list_head node;const char *name;unsigned int id;unsigned int base;//gpio空間此段gpio編號的開始unsigned int pin_base;//pinctrl空間此段pin空間的開始unsigned const *pins;unsigned int npins;//此段范圍總的引腳個數struct gpio_chip *gc;
}
圖示:
設備樹例子
以DesignWare的IP庫為例,led gpio和pinctrl為兩個外設
led設備設備樹:
leds {compatible = "gpio-leds";pinctrl-names = "default";pinctrl-0 = <&leds_gpio>;status = "okay";heartbeat {label = "Heartbeat";gpios = <&port1 23 GPIO_ACTIVE_HIGH>;linux,default-trigger = "heartbeat";};};
gpio外設設備樹:
gpio@地址 {compatible = "snps,dw-apb-gpio";reg = <0x0xxxxxxx 0xxxxx>;#address-cells = <1>;#size-cells = <0>;port1: gpio@0 {compatible = "snps,dw-apb-gpio-port";gpio-controller;#gpio-cells = <2>;snps,nr-gpios = <32>;reg = <0>;};port2: gpio@1 {compatible = "snps,dw-apb-gpio-port";gpio-controller;#gpio-cells = <2>;snps,nr-gpios = <32>;reg = <1>;};};
pinctrl外設設備樹:
pinctrl@地址 {leds_gpio: leds_gpio {xxx,pins = <PF5>; xxx,pull = <XXX_PULL_UP>;xxx,function = <XXX_FUNC_XXX>;};};
三、主要的數據結構
gpio子系統
struct gpio_chip:理解為一個gpio外設控制器或者gpio外設控制器下的某個端口的表示(每個端口有一組引腳);
struct gpio_device: struct gpio_chip的另一種表示,包含struct gpio_descs和struct gpio_chip的指針;
struct gpio_descs: 某個gpio外設或者gpio外設控制器下的某個端口下的某個引腳的表示,如一個外設或者端口下有個32個引腳那么每個引腳都會分配一個這樣的結構;
pinctrl子系統
struct pinctrl:具體的設備在獲取pinctrl-0屬性前會生成一個這個結構,其中的 dev執行具體設備的dev;
struct pinctrl_dev: 包括 struct pin_desc ,struct pinctrl_desc 等;
struct pinctrl_gpio_range: 定義gpio和pinctrl一段引腳映射的關系;
struct pinctrl_map:對引腳的配置的一種表示,比如a引腳上拉是一個map,a引腳為gpio是一個map,其中的type成員會具體區分;
struct pin_desc: 關注成員gpio_owner;
struct pinctrl_pin_desc :注意和struct pin_desc的區分,表示pin號和pin的名字;
四、驅動初始化流程
1、pinctrl外設解析注冊過程
xxxxx_probe(pinctrl-xxxx.c)->
devm_pinctrl_register(core.c) ->
pinctrl_register(core.c)->
pinctrl_enable 注冊pinctrl外設到核心層的隊列pinctrldev_list里;
調用過程中會涉及到pinctrl子系統中以上主要數據struct pinctrl_dev, struct pinctrl_pin_desc ,struct pin_desc等的創建和初始化;
2、具體設備根據設備中引腳的配置調用struct pinctrl_dev 的 struct pinctrl_desc的struct pinmux_ops鉤子函數配置引腳
內核源碼/drivers/base/dd.c ->
pinctrl_init_done(core.c)->
pinctrl_commit_state (core.c)->
pinmux_enable_setting (pinmux.c)->
pinmux_ops *ops->set_mux( pinctrl-xxxx.c 中注冊的struct pinmux_ops 成員)
3、具體設備調用struct pinctrl_dev 的 struct pinctrl_desc的pinctrl_ops的 dt_node_to_map,通過解析具體設備的引腳配置生成 pinctrl_map的過程
內核源碼/drivers/base/pinctrl.c -> devm_pinctrl_get(core.c)->
pinctrl_get(core.c)->
create_pinctrl(dev, NULL);(pinctrl/core.c) ->
pinctrl_dt_to_map(devicetree.c) 循環調用 ->
dt_to_map_one_config(devicetree.c )->
dt_node_to_map(pinctrl-xxxx.c 中注冊的struct pinctrl_ops 成員)
設備在解析設備樹獲取引腳配置時會根據設備的設備樹pinctrl-0等狀態生成struct pinctrl結構,解析設備樹引腳配置生成 struct pinctrl_map 并掛到struct pinctrl的鏈表成員中,需要仔細看代碼理解;
五、難點說明
1、pinctrl子系統struct pinctrl_map 結構說明
struct pinctrl_map {const char *dev_name;const char *name;enum pinctrl_map_type type; //const char *ctrl_dev_name;union {struct pinctrl_map_mux mux;struct pinctrl_map_configs configs;} data;
};
以上述led設備樹為例,會生成兩個map,解析xxx,function屬性生成一個成員type類型PIN_MAP_TYPE_MUX_GROUP的map,解析xxx,pull生成一個成員type類型PIN_MAP_TYPE_CONFIGS_PIN的map;