长沙蒲公英网站建设/企业网站托管

长沙蒲公英网站建设,企业网站托管,wordpress标题截断,0经验自己做网站以下代码都在pinctrl相关的驱动函数和设备树中 pinctrl-rockchip.c驱动,对应的是那个(那些)设备树呢? 答案:通过.compatible "rockchip,rk3568-pinctrl"连接到rk3568.dtsi根节点下的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.mzph.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 分…

c语言笔记 字符串函数---strcmp,strncmp,strchr,strrchr

目录 函数strcmp与strncmp 以下是错误的示范&#xff1a;两个指针字符型的指针不能直接进行比较 函数strchr与函数strrchr 函数strchr与函数strrchr与strstr函数三者对比 背景&#xff1a;如果说我们要比较两个字符串是否相等&#xff0c;使用strcmp或者strncmp函数。在c语言中…

IDEA集成git,项目的克隆,远程仓库中文件的添加删除

目录 一、克隆项目 二、使用IDEA完成文件的上传和删除 1.配置git 2.上传 3.删除&#xff08;通过git bash&#xff09; 一、克隆项目 点击克隆&#xff0c;复制url &#xff0c;如下 打开你想要克隆到哪里&#xff0c;右击&#xff0c;选择 open Git Bash here 这一步之后…

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.确定文件格式 使用命…

网页制作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…

Docker封装镜像、分发、部署实践:nginx

在实际生产工作中&#xff0c;通常是没法直接访问公网的&#xff0c;但是有经常需要使用Docker部署应用&#xff0c;本文将介绍使用Docker从拉取nginx、打包、分发到加载部署nginx的全流程&#xff01; 1 准备工作 1.1 安装docker 请参考&#xff1a;Docker入门指南&#xff…

Ollama+OpenWebUI本地部署大模型

OllamaOpenWebUI本地部署大模型 前言Ollama使用Ollama安装Ollama修改配置Ollama 拉取远程大模型Ollama 构建本地大模型Ollama 运行本地模型&#xff1a;命令行交互Api调用Web 端调用 总结 前言 Ollama是一个开源项目&#xff0c;用于在本地计算机上运行大型语言模型&#xff0…

【机器学习】基于t-SNE的MNIST数据集可视化探索

一、前言 在机器学习和数据科学领域&#xff0c;高维数据的可视化是一个极具挑战但又至关重要的问题。高维数据难以直观地理解和分析&#xff0c;而有效的可视化方法能够帮助我们发现数据中的潜在结构、模式和关系。本文以经典的MNIST手写数字数据集为例&#xff0c;探讨如何利…

K8S学习之基础二十三:k8s的持久化存储之nfs

K8S持久化存储之nfs ​ 在 Kubernetes (k8s) 中使用 NFS&#xff08;Network File System&#xff09;作为存储解决方案是一种常见的方式&#xff0c;特别是在需要共享存储的场景中。以下是关于如何在 Kubernetes 中使用 NFS 存储的详细说明&#xff1a; 1. 准备 NFS 服务器 …

《C++ Primer》学习笔记(二)

第二部分&#xff1a;C标准库 1.为了支持不同种类的IO处理操作&#xff0c;标准库定义了以下类型的IO&#xff0c;分别定义在三个独立的文件中&#xff1a;iostream文件中定义了用于读写流的基本类型&#xff1b;fstream文件中定义了读写命名文件的类型&#xff1b;sstream文件…

MATLAB风光柴储微网粒子群算法

本程序实现了风光柴储微网中的粒子群优化&#xff08;PSO&#xff09;算法&#xff0c;用于优化微网的能源调度问题。具体来说&#xff0c;程序考虑了光伏发电、风力发电、柴油机发电&#xff08;柴储&#xff09;&#xff0c;并使用粒子群算法来优化这些能源的调度&#xff0c…

解决Windows版Redis无法远程连接的问题

&#x1f31f; 解决Windows版Redis无法远程连接的问题 在Windows系统下使用Redis时&#xff0c;很多用户会遇到无法远程连接的问题。尤其是在配置了Redis并尝试通过工具如RedisDesktopManager连接时&#xff0c;可能会报错“Cannot connect to ‘redisconnection’”。今天&am…