2. 管理這些pin的復用(Multiplexing)。對於SOC而言,其引腳除了配置成普通GPIO之外,若干個引腳還可以組成一個pin group,形成特定的功能。例如pin number是{ 0, 8, 16, 24 }這四個引腳組合形成一個pin group,提供SPI的功能。pin control subsystem要管理所有的pin group。
3. 配置這些pin的特性。例如配置該引腳上的pull-up/down電阻,配置drive strength等。
4. 與GPIO子系統的交互
5. 實現pin中斷
1.3 [b]總體框架[/b]
arch/arm/mach-sunxi/ sys_config.c //分析、處理sys_config.fex文件。
drivers/pinctrl/ core.c //創建debug fs,提供pinctrl_register等函數接口。
drivers/pinctrl/ pinctrl-sun8iw7.c //該平台下的pin腳數據
1 sunxi_pinctrl_probe函數:
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); // devm_kzalloc基於slab分配在物理上連續的實際的內存,
並且帶有釋放內存的回調函數,當該設備與驅動分開時,自動釋放內存。
pctl->desc = (struct sunxi_pinctrl_desc *)(&sunxi_pinctrl_data);
1.1 sunxi_pinctrl_build_state(pdev);//將pctl->desc的子項數據復制到pctl相應子項。
1.2 pctl->pctl_dev = pinctrl_register(&sunxi_pctrl_desc, &pdev->dev, pctl); //創建pinctrl_dev設備,調用pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);注冊所有的pin。
1.2.1 pinctrl_register_pins對每一個pin腳調用 ret=pinctrl_register_one_pin(pctldev, pins[i].number, pins[i].name); //將pin
的物理地址,名字存入pin_desc結構體,將該結構體加入pin_desc_tree鏈表。
1.2.2 pctldev->p = pinctrl_get_locked(pctldev->dev); //先調用find_pinctrl從pinctrl_list鏈表中查找看pin control state holder是否存在;存在,即表明其正在使用中;不存在時,調用create_pinctrl創建pinctrl,從pinctrl_maps鏈表查找對應dev的maps_node,而maps裡面的數據是從sys_config.fex文件分析獲取,詳見1.5。如找到對應的maps_node,則調用add_setting(p,
map);該函數針對map->type填充pinctrl_setting相應成員變量,如果是PIN_MAP_TYPE_MUX_GROUP類型,填充之後,還會調用pin_request注冊同組中所有的pin。
最後將pinctrl加入pinctrl_list鏈表。
1.2.3 pinctrl_init_device_debugfs(pctldev); //注冊debugfs
1.3 gpiochip_add //GPIO驅動將通過chip來與pinctrl聯系,相應的操作將通過sunxi_pinctrl_gpio_chip結構的方法成員實現相應的操作。
將全局變量gpio_desc的成員變量chip、flags賦初值。後續GPIO相應操作將通過gpio_desc進行。
1.3.1 of_gpiochip_add(chip);
初始化chip的相應變量,並增加chip->of_node的引用計數
1.3.2 gpiochip_export(chip)
創建gpiochip0設備,其屬性文件用來show chip->ngpio, chip->label, chip->base
1.4 gpiochip_add_pin_range 建立動態鏈表chip->pin_ranges,node為gpio_pin_range,其成員range包含pin腳基地址。
1.5 sunxi_pinctrl_parse_pin_cfg (pdev); //分析獲取sys_config.fex文件中的配置,
1.5.1 sunxi_pinctrl_creat_mappings(pdev, pin_count, pin_list, device_name, state_name); //用配置數據填充pinctrl_map
1.5.2 pinctrl_register_mappings //創建pinctrl_maps,將pinctrl_map賦值給其maps成員變量,並加入pinctrl_maps鏈表。
1.6 sunxi_eint_gpio_init //注冊中斷
(2) drivers/gpio/ gpio-sunxi.c
1. gpio_sw_init // 讀取sys_config.fex文件中gpio_para參數對應的配置數據組,有單獨led_assign進行處理
1.1 gpio_request //向pinctrl請求pin用作GPIO,成功後,該Pin僅能被GPIO驅動所使用,不能被其他驅動所混用
通過本文件的靜態結構數組gpio_desc找到對應的pin腳的設置,具體數據見Pinctrl-sun8iw7.c (drivers\pinctrl)
chip->request 等價於執行 sunxi_pinctrl_gpio_chip. Request = sunxi_pinctrl_gpio_request
-> pinctrl_request_gpio -> pinmux_request_gpio -> pin_request -> pctldev->desc->pmxops->
(1. gpio_request_enable 2. request)
1.2 platform_device_register(gpio_sw_dev[i]) //注冊平台設備
gpio_sw_dev[i]->name = "gpio_sw";
gpio_sw_dev[i]->id = i;
gpio_sw_dev[i]->dev.platform_data = sw_pdata[i];
gpio_sw_dev[i]->dev.release = gpio_sw_release;
1.3 platform_driver_register(&gpio_sw_driver)
注冊gpio_sw驅動,
gpio_sw_probe: 調用gpio_sw_cfg_set及gpio_sw_data_set函數根據參數配置設置,調用gpio_sw_classdev_register創建相應的設備屬性文件,即提供接口給上層,如上接,寫1/0等操作。根據sw_pdata->link創建超鏈接
/sys/class/gpio_sw /normal_led -> PA15
/sys/class/gpio_sw /standby_led -> PL10
/sys/devices/platform/gpio_sw.0/gpio_sw/PL10/cfg
/sys/devices/platform/gpio_sw.1/gpio_sw/PA15/cfg
struct pinctrl *pinctrl_get(struct device *dev) à p = pinctrl_get_locked(dev);
第641行調用find_pinctrl函數
第645行調用create_pinctrl,獲取pinctrl結構體
pinctrl_put
devm_pinctrl_get
devm_pinctrl_put
pinctrl_lookup_state //查找pinctrl_state
pinctrl_select_state //將pin句柄對應的pinctrl設置為state句柄對應的狀態,其核心為通過pinmux_enable_setting或pinconf_apply_setting來調用pinctrl_desc的ops來設置pin狀態。
devm_pinctrl_get_select
devm_pinctrl_get_select_default
pin_config_get //獲取指定pin的屬性,最終是通過confops->pin_config_get獲取
pin_config_set //設置指定pin的屬性,最終是通過confops->pin_config_set設置
pin_config_group_get //與上類似,pin_config_group_get
pin_config_group_set //與上類似,pin_config_group_set
gpio_free
gpio_direction_input
gpio_direction_output
__gpio_get_value
__gpio_set_value
lichee/tools/pack/chips/sun8iw7p1/configs/dolphin-p1/sys_config.fex 參照如下配置即可:
;----------------------------------------------------------------------------------
;userspace gpio interface for android
;----------------------------------------------------------------------------------
[gpio_para]
gpio_used = 1
gpio_num = 2
gpio_pin_1 = port:PL10<1><default><default><1>
gpio_pin_2 = port:PA15<1><default><default><0>
a. 向應用層提供的接口文件如下:
/sys/devices/platform/gpio_sw.0/gpio_sw/PL10/
/sys/devices/platform/gpio_sw.1/gpio_sw/PA15/
b. 內核其他模塊使用:
#include <linux/gpio.h>
__gpio_get_value
__gpio_set_value
2. 非GPIO驅動模塊的使用
#include <linux/pinctrl/consumer.h>
devm_pinctrl_get
pinctrl_lookup_state
pinctrl_select_state
http://www.wowotech.net/gpio_subsystem/pin-control-subsystem.html/ comment-page-2#comments