04_Linux驅動_05_pinctrl子系統

以下代碼都在pinctrl相關的驅動函數和設備樹中

pinctrl-rockchip.c驅動,對應的是那個(那些)設備樹呢?

答案:通過.compatible = "rockchip,rk3568-pinctrl"連接到rk3568.dtsi根節點下的pinctrl節點

一,pinctrl_desc結構體

/*用于描述 Pin controller
*/
struct pinctrl_desc {const char *name;                    //1,名字const struct pinctrl_pin_desc *pins; //2,一個引腳unsigned int npins;                  //3,一共有多少引腳const struct pinctrl_ops *pctlops;   //4,xxx操作集合const struct pinmux_ops *pmxops;     //5,xxx操作集合const struct pinconf_ops *confops;   //6,xxx操作集合struct module *owner;                //7,模塊的擁有者
#ifdef CONFIG_GENERIC_PINCONFunsigned int num_custom_params;      //自定義相關const struct pinconf_generic_params *custom_params;const struct pin_config_item *custom_conf_items;
#endif
};

????????構建完 pinctrl結構體之后,會調用pinctrl_register函數注冊一個pinctrl控制器,得到一個pinctrl_dev

1.1pinctrl_desc結構體在probe中的使用

不同的芯片廠,的pinctrl的驅動不一樣,我的被打包到了rockchip_pinctrl結構體之中了!!!


struct rockchip_pinctrl {struct regmap			*regmap_base;int				reg_size;struct regmap			*regmap_pull;struct regmap			*regmap_pmu;struct device			*dev;struct rockchip_pin_ctrl	*ctrl;struct pinctrl_desc		pctl;            //在這里struct pinctrl_dev		*pctl_dev;struct rockchip_pin_group	*groups;unsigned int			ngroups;struct rockchip_pmx_func	*functions;unsigned int			nfunctions;
};

1.2用rockchip_pinctrl_register函數進行注冊。

ret = rockchip_pinctrl_register(pdev, info);
if (ret)return ret;--->>進入rockchip_pinctrl_register函數
{struct pinctrl_desc *ctrldesc = &info->pctl;struct pinctrl_pin_desc *pindesc, *pdesc;struct rockchip_pin_bank *pin_bank;int pin, bank, ret;int k;ctrldesc->name = "rockchip-pinctrl";    //驅動名字和compatible配對ctrldesc->owner = THIS_MODULE;          ctrldesc->pctlops = &rockchip_pctrl_ops;  //三個操作集合ctrldesc->pmxops = &rockchip_pmx_ops;     //ctrldesc->confops = &rockchip_pinconf_ops;////給管腳申請內存空間pindesc = devm_kcalloc(&pdev->dev,info->ctrl->nr_pins, sizeof(*pindesc),GFP_KERNEL);if (!pindesc)return -ENOMEM;ctrldesc->pins = pindesc;ctrldesc->npins = info->ctrl->nr_pins;//給管腳 編號 命名pdesc = pindesc;for (bank = 0, k = 0; bank < info->ctrl->nr_banks; bank++) {pin_bank = &info->ctrl->pin_banks[bank];for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) {pdesc->number = k;pdesc->name = kasprintf(GFP_KERNEL, "%s-%d",pin_bank->name, pin);pdesc++;}}//在devm_pinctrl_register中調用pinctrl_register函數進行注冊ret = rockchip_pinctrl_parse_dt(pdev, info);if (ret)return ret;info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info);if (IS_ERR(info->pctl_dev)) {dev_err(&pdev->dev, "could not register pinctrl driver\n");return PTR_ERR(info->pctl_dev);}}

二,pinctrl 子系統函數操作集

2.1 groups和function

groups(引腳組):

引腳組是一組具有相似功能、約束條件或共同工作的引腳的集合。

function(功能):

定義了芯片上具有外設功能的功能。每個功能節點對應于一個或多個 IO 組(group)的配置信息。這些功能可以是串口、SPI、I2C 等外設功能。

在.dtsi文件中:

    can0 {                              //這是一個function/omit-if-no-ref/                //這是一組groupscan0m0_pins: can0m0-pins {rockchip,pins =/* can0_rxm0 */<0 RK_PB4 2 &pcfg_pull_none>,/* can0_txm0 */<0 RK_PB3 2 &pcfg_pull_none>;};/omit-if-no-ref/                 //這是一另組groupscan0m1_pins: can0m1-pins {rockchip,pins =/* can0_rxm1 */<2 RK_PA2 4 &pcfg_pull_none>,/* can0_txm1 */<2 RK_PA1 4 &pcfg_pull_none>;};};can1 {                               //這是一另個function                  /omit-if-no-ref/can1m0_pins: can1m0-pins {rockchip,pins =/* can1_rxm0 */<1 RK_PA0 3 &pcfg_pull_none>,/* can1_txm0 */<1 RK_PA1 3 &pcfg_pull_none>;};/omit-if-no-ref/can1m1_pins: can1m1-pins {rockchip,pins =/* can1_rxm1 */<4 RK_PC2 3 &pcfg_pull_none>,/* can1_txm1 */<4 RK_PC3 3 &pcfg_pull_none>;};};

可已這么說:can0和can1對應2個function,為CAN0控制器和CAN1控制器,而每個控制器中又有2給不同的groups引腳組

2.2pinctrl_ops結構體:

里面都是函數。

struct pinctrl_ops {//獲取設備樹中的groups用了多少個int (*get_groups_count) (struct pinctrl_dev *pctldev);//獲取指定groups的名字const char *(*get_group_name) (struct pinctrl_dev *pctldev,unsigned selector);//獲取指定groups的管腳int (*get_group_pins) (struct pinctrl_dev *pctldev,unsigned selector,const unsigned **pins,unsigned *num_pins);//調試用void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,unsigned offset);//節點轉化為mapint (*dt_node_to_map) (struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, unsigned *num_maps);//dt_node_to_map的反操作void (*dt_free_map) (struct pinctrl_dev *pctldev,struct pinctrl_map *map, unsigned num_maps);
};

2.3pinmux_ops結構體:

/*  pinctrl_dev:代表著一個 pin controller*/
struct pinmux_ops {//1,申請引腳int (*request) (struct pinctrl_dev *pctldev, unsigned offset);//2,釋放引腳int (*free) (struct pinctrl_dev *pctldev, unsigned offset);//3,獲取 pin controller 中 function 的數量int (*get_functions_count) (struct pinctrl_dev *pctldev);//4,獲取指定 function 的名字const char *(*get_function_name) (struct pinctrl_dev *pctldev,unsigned selector);//5,獲取指定 function 的 groupsint (*get_function_groups) (struct pinctrl_dev *pctldev,unsigned selector,const char * const **groups,unsigned *num_groups);//6,設定引腳的 復用功能 (GPIO/I2C/SPI...)int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector,unsigned group_selector);//7,申請并使能 GPIOint (*gpio_request_enable) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset);//8,禁止并釋放 GPIOvoid (*gpio_disable_free) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset);//9,設置GPIO的方向int (*gpio_set_direction) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset,bool input);//不允許同時在同一個引腳上使用 GPIO 和 其他功能 (在同一時間,只能用一個功能)bool strict;
};

2.4pinconf_ops結構體:

struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONFbool is_generic;
#endif//1,獲取某個引腳的配置int (*pin_config_get) (struct pinctrl_dev *pctldev,unsigned pin,unsigned long *config);//2,設置某個引腳的配置int (*pin_config_set) (struct pinctrl_dev *pctldev,unsigned pin,unsigned long *configs,unsigned num_configs);//3,設置某個組的引腳配置int (*pin_config_group_get) (struct pinctrl_dev *pctldev,unsigned selector,unsigned long *config);//4,獲取某個組的引腳配置int (*pin_config_group_set) (struct pinctrl_dev *pctldev,unsigned selector,unsigned long *configs,unsigned num_configs);//6,解析和修改調試信息int (*pin_config_dbg_parse_modify) (struct pinctrl_dev *pctldev,const char *arg,unsigned long *config);//789,調試使用void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev,struct seq_file *s,unsigned offset);void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,struct seq_file *s,unsigned selector);void (*pin_config_config_dbg_show) (struct pinctrl_dev *pctldev,struct seq_file *s,unsigned long config);
};

2.5rockchip_pinctrl 進一步分析

在1.1中我看到了struct pinctrl_desc,在pinctrl_desc結構體里有:

struct rockchip_pin_group *groups;   //瑞芯微芯片引腳組指針
unsigned int ngroups;                //引腳組數量
struct rockchip_pmx_func *functions; //瑞芯微芯片引腳功能指針
unsigned int nfunctions;             //引腳功能數量

這四個變量被在pinctrl的probe函數中-->rockchip_pinctrl_register函數中的rockchip_pinctrl_parse_dt函數處理:


static int rockchip_pinctrl_register(struct platform_device *pdev,struct rockchip_pinctrl *info)
{struct pinctrl_desc *ctrldesc = &info->pctl;struct pinctrl_pin_desc *pindesc, *pdesc;struct rockchip_pin_bank *pin_bank;int pin, bank, ret;int k;ctrldesc->name = "rockchip-pinctrl";ctrldesc->owner = THIS_MODULE;ctrldesc->pctlops = &rockchip_pctrl_ops;    //瑞芯微封裝的操作集1ctrldesc->pmxops = &rockchip_pmx_ops;       //瑞芯微封裝的操作集2ctrldesc->confops = &rockchip_pinconf_ops;  //瑞芯微封裝的操作集3pindesc = devm_kcalloc(&pdev->dev,info->ctrl->nr_pins, sizeof(*pindesc),GFP_KERNEL);if (!pindesc)return -ENOMEM;ctrldesc->pins = pindesc;ctrldesc->npins = info->ctrl->nr_pins;pdesc = pindesc;for (bank = 0, k = 0; bank < info->ctrl->nr_banks; bank++) {pin_bank = &info->ctrl->pin_banks[bank];for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) {pdesc->number = k;pdesc->name = kasprintf(GFP_KERNEL, "%s-%d",pin_bank->name, pin);pdesc++;}}//rockchip_pinctrl_parse_dt在這個函數里處理了上面四個變量ret = rockchip_pinctrl_parse_dt(pdev, info);if (ret)return ret;info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info);if (IS_ERR(info->pctl_dev)) {dev_err(&pdev->dev, "could not register pinctrl driver\n");return PTR_ERR(info->pctl_dev);}return 0;
}

2.6函數操作集的具體實現

? ?都是調用pinctrl_dev_get_drvdata函數來處理

?

static const struct pinctrl_ops rockchip_pctrl_ops = {.get_groups_count	= rockchip_get_groups_count,.get_group_name		= rockchip_get_group_name,.get_group_pins		= rockchip_get_group_pins,.dt_node_to_map		= rockchip_dt_node_to_map,.dt_free_map		= rockchip_dt_free_map,
};

static const struct pinmux_ops rockchip_pmx_ops = {.get_functions_count	= rockchip_pmx_get_funcs_count,.get_function_name	= rockchip_pmx_get_func_name,.get_function_groups	= rockchip_pmx_get_groups,.set_mux		= rockchip_pmx_set,
};

static const struct pinconf_ops rockchip_pinconf_ops = {.pin_config_get			= rockchip_pinconf_get,.pin_config_set			= rockchip_pinconf_set,.is_generic			= true,
};

三,dt_node_to_map函數

????????設備樹(Device Tree)中存放的是對硬件設備信息的描述,包含了硬件設備的配置和連接信息,例如在pinctrl節點中的引腳的配置和映射關系。而rockchip_dt_node_to_map函數的作用就是根據設備樹中的節點信息,生成對應的引腳映射數組。這個映射數組將描述硬件功能(如 復用功能和配置信息)與設備樹中的引腳信息進行綁定。

3.1pinctrl_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;
};

需要將設備樹上的信息來轉化為驅動中可以用的函數,放在pinctrl_map結構體中

3.2dt_node_to_map流程分析

/**傳入參數:*1,pin control class device*2,設備樹中的一個node信息*3,略*4,略*/
static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,struct device_node *np,struct pinctrl_map **map, unsigned *num_maps)
{//獲取pinctrl信息struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);const struct rockchip_pin_group *grp;struct pinctrl_map *new_map;            //要轉化為的map數據struct device_node *parent;             //存放傳入節點的父節點int map_num = 1;int i;/** 通過節點的名字獲取組的信息,并且檢查是否需要創建配置映射*/grp = pinctrl_name_to_group(info, np->name);if (!grp) {dev_err(info->dev, "unable to find group for node %pOFn\n",np);return -EINVAL;}/**grp->npins:是獲取的組里引腳的數量*/map_num += grp->npins;/**分配map_num數量的內存,首地址放在new_map中*/new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);if (!new_map)return -ENOMEM;*map = new_map;*num_maps = map_num;/* create mux map */parent = of_get_parent(np);if (!parent) {kfree(new_map);return -EINVAL;}//引腳配置信息的父節點寫入map中new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;new_map[0].data.mux.function = parent->name;new_map[0].data.mux.group = np->name;of_node_put(parent);/* create config map */new_map++;for (i = 0; i < grp->npins; i++) {                //遍歷每一個成員//引腳配置信息寫入map中new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;new_map[i].data.configs.group_or_pin =pin_get_name(pctldev, grp->pins[i]);new_map[i].data.configs.configs = grp->data[i].configs;new_map[i].data.configs.num_configs = grp->data[i].nconfigs;}dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",(*map)->data.mux.function, (*map)->data.mux.group, map_num);return 0;
}

四,開發板上用到的pinctrl

在設備樹下的兩個部分:

//1,在rk3568-evb1-ddr4-v10.dtsi文件的根目錄下//是一個設備,pinctrl的客戶端rk_485_ctl: rk-485-ctl {compatible = "topeet,rs485_ctl";gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&rk_485_gpio>;    //這里就是引用了2部分的rk_485_gpio};//2,在rk3568-evb1-ddr4-v10.dtsi里的
//服務端
&pinctrl {cam {camera_pwr: camera-pwr {rockchip,pins =/* camera power en */<0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;};};headphone {hp_det: hp-det {rockchip,pins = <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;};};rk_485{rk_485_gpio:rk-485-gpio {rockchip,pins = <3 13 RK_FUNC_GPIO &pcfg_pull_none>;};};
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/72328.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72328.shtml
英文地址,請注明出處:http://en.pswp.cn/web/72328.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python的那些事第四十五篇:繼承自Nose的測試框架Nose2

Nose2:繼承自Nose的測試框架 摘要 本文深入探討了Nose2這一繼承自Nose的測試框架。在軟件開發過程中,測試是確保代碼質量和穩定性的重要環節,而測試框架為測試工作的開展提供了有力支持。Nose2作為Nose的繼承者,在保留Nose優勢的基礎上進行了諸多改進和擴展,為Python測試…

如何通過 Airbyte 將數據攝取到 Elasticsearch

作者&#xff1a;來自 Elastic Andre Luiz Airbyte 是一個數據集成工具&#xff0c;可自動化并可擴展地將信息從各種來源傳輸到不同的目的地。它使你能夠從 API、數據庫和其他系統提取數據&#xff0c;并將其加載到 Elasticsearch 等平臺&#xff0c;以實現高級搜索和高效分析。…

RBAC 模型的簡單實現

RBAC 模型基本介紹 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的訪問控制&#xff09;是一種廣泛應用的權限管理模型。它的核心思想是通過角色來管理權限&#xff0c;而不是直接分配權限給用戶。用戶被賦予一個或多個角色&#xff0c;而每個角色擁有不同…

數據結構---堆棧和列

一、堆棧 1.棧堆&#xff1a;具有一定操作約束的線性表&#xff1b;&#xff08;只在一端做插入刪除&#xff09; 2.棧的順序存儲結構&#xff1a; 由一個一維數組和一個記錄棧頂元素位置的變量組成。定義方式如下&#xff1a; 3.入棧操作&#xff1a; 注意&#xff1a;&…

2023 年全國職業院校技能大賽(中職組)移動應用與開發賽項 賽題第十套

2023 年全國職業院校技能大賽&#xff08;中職組&#xff09;移動應用與開發賽項 賽題第十套&#xff09; 移動應用與開發賽項競賽模塊 A&#xff1a;移動應用界面設計任務 1 環保中心界面設計&#xff08;7.5 分&#xff09;任務 2&#xff1a;首頁界面設計&#xff08;7.5 分…

FPGA為何要盡量減少組合邏輯的使用

在FPGA設計中&#xff0c;組合邏輯的使用確實需要謹慎&#xff0c;尤其是要盡量減少它的復雜性。這并不是因為組合邏輯本身不好&#xff0c;而是因為它在實際應用中容易引發一系列問題&#xff0c;而這些問題往往與FPGA的設計哲學和硬件特性相沖突。讓我從幾個關鍵點來和你聊聊…

c語言筆記 字符串函數---strcmp,strncmp,strchr,strrchr

目錄 函數strcmp與strncmp 以下是錯誤的示范&#xff1a;兩個指針字符型的指針不能直接進行比較 函數strchr與函數strrchr 函數strchr與函數strrchr與strstr函數三者對比 背景&#xff1a;如果說我們要比較兩個字符串是否相等&#xff0c;使用strcmp或者strncmp函數。在c語言中…

合React寶寶體質的自定義節流hook

本文為開發開源項目的真實開發經歷&#xff0c;感興趣的可以來給我的項目點個star&#xff0c;謝謝啦~ 具體博文介紹&#xff1a; 開源&#xff5c;Documind協同文檔&#xff08;接入deepseek-r1、支持實時聊天&#xff09;Documind &#x1f680; 一個支持實時聊天和接入 - 掘…

【RTSP】客戶端(五)H264 265處理邏輯

H264處理邏輯 整體邏輯分析 實現邏輯 解析 RTP 包頭&#xff1a;首先檢查 RTP 頭部的有效負載類型&#xff08;payloadType&#xff09;是否匹配處理擴展頭&#xff1a;如果 RTP 包包含擴展頭&#xff0c;跳過擴展頭部分&#xff0c;獲取有效負載處理分片數據&#xff1a;H264…

IDEA集成git,項目的克隆,遠程倉庫中文件的添加刪除

目錄 一、克隆項目 二、使用IDEA完成文件的上傳和刪除 1.配置git 2.上傳 3.刪除&#xff08;通過git bash&#xff09; 一、克隆項目 點擊克隆&#xff0c;復制url &#xff0c;如下 打開你想要克隆到哪里&#xff0c;右擊&#xff0c;選擇 open Git Bash here 這一步之后…

神經網絡:定義與核心原理

神經網絡&#xff08;Artificial Neural Network, ANN&#xff09;是一種受生物神經系統啟發的計算模型&#xff0c;旨在通過模擬神經元之間的連接與信息傳遞機制&#xff0c;實現復雜的數據處理和模式識別功能。其本質是由大量簡單處理單元&#xff08;神經元&#xff09;構成…

將pdf或者word轉換成base64格式

廢話不多說直接上代碼&#xff1a; function fileToBase64(file) {return new Promise((resolve, reject) > {const reader new FileReader();reader.readAsDataURL(file);reader.onload function (event) {const base64Data event.target.result.split(,)[1];resolve(b…

Spring @Bean注解使用場景二

bean:最近在寫一篇讓Successfactors顧問都能搞明白的sso的邏輯的文章&#xff0c;所以一致在研究IAS的saml2.0的協議&#xff0c;希望用代碼去解釋SP、idp的一些概念&#xff0c;讓顧問了解SSO與saml的關系&#xff0c;在github找代碼的時候發現一些代碼的調用關系很難理解&…

ubuntu22.04 關于掛在設備為nfts文件格式無法創建軟連接的問題

最近遇到情況&#xff0c;解壓工程報錯&#xff0c;無法創建軟連接 但是盤內還有130G空間&#xff0c;明顯不是空間問題&#xff0c;查找之后發現是移動硬盤的文件格式是NTFS&#xff0c;在ubuntu上不好兼容&#xff0c;于是報錯。 開貼記錄解決方案。 1.確定文件格式 使用命…

docker后臺運行,便于后期用命令行進入它的終端

在 docker compose up --build -d 命令中&#xff0c;?**-d?&#xff08;或 --detach&#xff09;參數的作用是讓容器以后臺模式&#xff08;detached mode&#xff09;?**運行。以下是詳細解釋&#xff1a; ?**-d 參數的作用** ?后臺運行容器&#xff1a; 默認情況下&a…

網頁制作14-Javascipt時間特效の顯示動態日期

<!doctype html> <html> <head> <meta charset"utf-8"> <title>動態日期</title> </head><script>var today new Date();//獲取時間var ytoday.getFullYear();//截取年var mtoday.getMonth();//截取月份,返回0~11v…

【BP神經網絡】實戰

1.參考Python實戰&#xff1a;BP神經網絡_bp神經網絡實戰python-CSDN博客 2.實踐 &#xff08;1&#xff09;運行環境 anocanda Powershell Prompt&#xff08;anocanda3&#xff09; &#xff08;2&#xff09;創建虛擬環境&#xff0c;解決安裝包的版本問題 *打開終端&a…

深度學習多模態人臉情緒識別:從理論到實踐

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站。https://www.captainbed.cn/north 文章目錄 1. 引言2. 技術框架與流程圖3. 核心算法解析3.1 視覺特征提取&#xff08;CNN&#xff09;3.2…

ssh通過22端口無法連接服務器問題處理

一&#xff0c;安全組開放22端口 root無法連接服務器&#xff0c;22端口也開放了&#xff0c;可能是防火墻開啟了攔截。 二&#xff0c;檢測防火墻狀態 查看防火墻狀態 sudo firewall-cmd --state 關閉防火墻 sudo systemctl stop firewalld 開啟防火墻 sudo systemctl sta…