歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux技術

全志H3平台pinctrl模塊分析

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 核心驅動源碼文件

1.3 [b]總體框架

[/b]

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

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);

第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.cgpio_request

gpio_free

gpio_direction_input

gpio_direction_output

__gpio_get_value

__gpio_set_value

2.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

Copyright © Linux教程網 All Rights Reserved