天天看點

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

1 概要

Linux核心中提供了pinctrl子系統,目的是為了統一各SoC廠商的pin腳管理,避免各SoC廠商各自實作相同的pin腳管理子系統,減少SoC廠商系統移植工作量。

1.1 主要功能

1. 管理系統中所有可以控制的pin。在系統初始化的時候,枚舉所有可以控制的pin,并辨別這些pin。

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.2 核心驅動源碼檔案

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

1.3 總體架構

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

2源碼分析

kernel配置檔案: lichee/linux-3.4/arch/arm/configs/sun8iw7p1smp_android_defconfig

系統配置檔案:lichee\tools\pack\chips\sun8iw7p1\configs\dolphin-p1\sys_config.fex

arch/arm/mach-sunxi/ sys_config.c //分析、處理sys_config.fex檔案。

drivers/pinctrl/ core.c //建立debug fs,提供pinctrl_register等函數接口。

drivers/pinctrl/ pinctrl-sun8iw7.c //該平台下的pin腳資料

2.1 驅動加載時主流程代碼

(1) drivers/pinctrl/ pinctrl-sunxi.c

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻
全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

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

2.2 向其他驅動子產品提供的接口函數

1. 非GPIO驅動子產品使用的接口:

pinctrl_get //擷取裝置的pin操作句柄

struct pinctrl *pinctrl_get(struct device *dev) à p = pinctrl_get_locked(dev); 

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

第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

2.3 GPIO驅動使用的接口

drivers/gpio/ gpiolib.c

gpio_request

gpio_free

gpio_direction_input

gpio_direction_output

__gpio_get_value

__gpio_set_value

2.4 各資料之間的聯系圖

全志H3平台pinctrl子產品分析1 概要2源碼分析3 使用方法及執行個體4 參考文獻

3 使用方法及執行個體

1. GPIO口配置:

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

4 參考文獻

1.《H3 Pinctrl(GPIO)接口使用說明V1.0.pdf》

2. http://www.wowotech.net/gpio_subsystem/pin-control-subsystem.html/ comment-page-2#comments