热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Linuxpinctrl子系统:数据结构详解

本文将详细探讨Linuxpinctrl子系统的各个关键数据结构,帮助读者深入了解其内部机制。通过分析这些数据结构及其相互关系,我们将进一步理解pinctrl子系统的工作原理和设计思路。

在前文我们已经介绍了pinctrl子系统的软件框架及各数据结构之间的关联。本章将进一步深入探讨每个核心数据结构的定义和作用,以加深对pinctrl子系统架构的理解。

我们将从SOC引脚描述、板级引脚描述以及设备模型与pinctrl子系统的关联三个方面进行详细说明。

SOC引脚描述相关数据结构

在之前的文章中,我们讨论了pinctrl子系统的基本概念,包括pin控制器设备(pin controller device)、pinctrl设备描述信息(pinctrl dev info)、引脚描述、功能(function)和组(group)等。

  1. PIN控制器设备抽象为struct pinctrl_dev,表示一个SOC上的PIN控制器。
  2. pinctrl dev info对应的数据结构是struct pinctrl_desc,它包含支持的引脚定义、配置接口、复用接口和组操作接口。
  3. 复用接口由struct pinmux_ops定义,提供了如申请、释放引脚、设置复用等功能。
  4. 组操作接口由struct pinctrl_ops定义,用于获取组的数量、名称及对应的引脚信息。
  5. 功能操作接口由struct pinconf_ops定义,用于设置和获取引脚配置。
  6. 针对每个引脚有struct pinctrl_pin_desc和struct pin_desc两个结构体,前者描述引脚名称和ID,后者记录引脚使用计数、当前所属的功能和组信息。

以下是这些数据结构之间的关联流程:

struct pinctrl_dev

该结构体是SOC PIN控制器的抽象,主要包含以下信息:

  1. struct pinctrl_desc类型的变量desc,描述pinctrl设备的信息。
  2. 基数树pin_desc_tree用于存储引脚使用情况,判断引脚是否被多次配置。
  3. 基数树pin_group_tree和pin_function_tree用于存储组和功能的描述信息。
  4. gpio_ranges链接GPIO范围到PIN范围的相关信息。
  5. device pin controller holder包含pinctrl_state信息,用于未具体分配给设备的引脚复用设置。

代码如下:

struct pinctrl_dev { struct list_head node; struct pinctrl_desc *desc; struct radix_tree_root pin_desc_tree; #ifdef CONFIG_GENERIC_PINCTRL_GROUPS struct radix_tree_root pin_group_tree; unsigned int num_groups; #endif #ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS struct radix_tree_root pin_function_tree; unsigned int num_functions; #endif struct list_head gpio_ranges; struct device *dev; struct module *owner; void *driver_data; struct pinctrl *p; struct pinctrl_state *hog_default; struct pinctrl_state *hog_sleep; struct mutex mutex; #ifdef CONFIG_DEBUG_FS struct dentry *device_root; #endif};

struct pinctrl_desc

此结构体描述pin ctrl设备的信息,主要包括:

  1. 所有引脚的描述信息(struct pinctrl_pin_desc *pins)和引脚数量。
  2. 引脚复用的操作接口(struct pinmux_ops *pmxops)。
  3. 引脚配置的操作接口(struct pinconf_ops *confops)。
  4. 组信息获取的操作接口(struct pinctrl_ops *pctlops)。
  5. 通用属性参数num_custom_params和custom_params,用于自定义引脚配置属性。

代码如下:

struct pinctrl_desc { const char *name; const struct pinctrl_pin_desc *pins; unsigned int npins; const struct pinctrl_ops *pctlops; const struct pinmux_ops *pmxops; const struct pinconf_ops *confops; struct module *owner; #ifdef CONFIG_GENERIC_PINCONF unsigned int num_custom_params; const struct pinconf_generic_params *custom_params; const struct pin_config_item *custom_conf_items; #endif};

struct pinctrl_pin_desc 和 struct pin_desc

这两个结构体分别描述引脚的基本信息和当前配置信息:

struct pinctrl_pin_desc { unsigned number; const char *name; void *drv_data; }; struct pin_desc { struct pinctrl_dev *pctldev; const char *name; bool dynamic_name; void *drv_data; #ifdef CONFIG_PINMUX unsigned mux_usecount; const char *mux_owner; const struct pinctrl_setting_mux *mux_setting; const char *gpio_owner; #endif};

struct pinctrl_ops

该结构体主要提供组操作接口:

  1. get_groups_count:获取组的数量。
  2. get_group_name:根据ID获取组名。
  3. get_group_pins:获取组内引脚信息。
struct pinctrl_ops { int (*get_groups_count) (struct pinctrl_dev *pctldev); const char *(*get_group_name) (struct pinctrl_dev *pctldev, unsigned selector); 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); int (*dt_node_to_map) (struct pinctrl_dev *pctldev, struct device_node *np_config, struct pinctrl_map **map, unsigned *num_maps); void (*dt_free_map) (struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps); };

struct pinmux_ops

该结构体定义了引脚复用相关的操作接口:

  1. request/free:申请或释放引脚。
  2. get_functions_count:获取所有功能的数量。
  3. get_function_name:根据ID获取功能名。
  4. get_function_groups:获取功能关联的组。
  5. set_mux:设置引脚复用。
  6. GPIO相关接口:enable、disable和direction配置。
struct pinmux_ops { int (*request) (struct pinctrl_dev *pctldev, unsigned offset); int (*free) (struct pinctrl_dev *pctldev, unsigned offset); int (*get_functions_count) (struct pinctrl_dev *pctldev); const char *(*get_function_name) (struct pinctrl_dev *pctldev, unsigned selector); int (*get_function_groups) (struct pinctrl_dev *pctldev, unsigned selector, const char * const **groups, unsigned *num_groups); int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector, unsigned group_selector); int (*gpio_request_enable) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); void (*gpio_disable_free) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); int (*gpio_set_direction) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input); bool strict; };

struct pinconf_ops

该结构体实现引脚配置相关的操作接口:

  1. pin_config_get:获取引脚配置。
  2. pin_config_set:设置引脚配置。
  3. pin_config_group_get:获取组配置。
  4. pin_config_group_set:设置组配置。
struct pinconf_ops { #ifdef CONFIG_GENERIC_PINCONF bool is_generic; #endif int (*pin_config_get) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config); int (*pin_config_set) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, unsigned num_configs); int (*pin_config_group_get) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config); int (*pin_config_group_set) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *configs, unsigned num_configs); 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); };
板级引脚描述相关数据结构

SOC引脚描述建立了SOC支持的所有引脚、功能、组及相关操作接口;而板级引脚描述则描述了具体板上使用的功能组合及引脚配置。主要涉及struct pinctrl_maps和struct pinctrl_map。

struct pinctrl_map

该结构体描述了一个功能类型,主要内容包括:

  1. dev_name:设备名称。
  2. name:状态名称(如default、idle、sleep)。
  3. type:pinctrl_map类型(如mux group、config group等)。
  4. ctrl_dev_name:pinctrl设备名称。
  5. data:包含引脚复用或配置的具体内容。
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; };

struct pinctrl_maps则是多个pinctrl_map的集合。

设备模型与pinctrl关联

前面介绍了SOC引脚描述和板级引脚描述,接下来我们将探讨设备模型与pinctrl子系统的关联。这部分涉及struct dev_pin_info、struct pinctrl、struct pinctrl_state和struct pinctrl_setting等数据结构。

struct dev_pin_info

该结构体描述设备的引脚配置与复用信息,主要内容包括:

  1. struct pinctrl类型的变量,表示支持的引脚配置状态。
  2. default_state:默认状态。
  3. init_state:初始化状态。
  4. 若支持电源管理,则还包括sleep和idle状态。
struct dev_pin_info { struct pinctrl *p; struct pinctrl_state *default_state; struct pinctrl_state *init_state; #ifdef CONFIG_PM struct pinctrl_state *sleep_state; struct pinctrl_state *idle_state; #endif };

struct pinctrl

该结构体描述设备的所有引脚配置信息:

struct pinctrl { struct list_head node; struct device *dev; struct list_head states; struct pinctrl_state *state; struct list_head dt_maps; struct kref users; };

struct pinctrl_state

该结构体表示设备引脚的一种状态及该状态下的引脚控制信息:

struct pinctrl_state { struct list_head node; const char *name; struct list_head settings; };

struct pinctrl_setting

该结构体表示设备在一个状态下的pinctrl控制信息:

struct pinctrl_setting { struct list_head node; enum pinctrl_map_type type; struct pinctrl_dev *pctldev; const char *dev_name; union { struct pinctrl_setting_mux mux; struct pinctrl_setting_configs configs; } data; };

借助于struct dev_pin_info,并结合board pin描述中的pinctrl_map信息和soc pin描述中的function、group信息,完成设备在每个状态下的引脚配置信息的设置,并实现引脚复用和配置操作。

总结:

  1. SOC引脚描述涵盖了所有支持的引脚、功能、组及相关操作接口。
  2. 板级引脚描述选择了SOC引脚描述中的一个子集。
  3. 设备模型与pinctrl关联部分根据设备相关的pinctrl map信息确定了所有状态下所对应的mux、group/pin config信息,并依据当前状态进行配置。

下一章我们将介绍具体的函数实现。


推荐阅读
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • 本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。 ... [详细]
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • Linux环境下C语言实现定时向文件写入当前时间
    本文介绍如何在Linux系统中使用C语言编程,实现在每秒钟向指定文件中写入当前时间戳。通过此示例,读者可以了解基本的文件操作、时间处理以及循环控制。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • Kubernetes 持久化存储与数据卷详解
    本文深入探讨 Kubernetes 中持久化存储的使用场景、PV/PVC/StorageClass 的基本操作及其实现原理,旨在帮助读者理解如何高效管理容器化应用的数据持久化需求。 ... [详细]
  • 本文介绍了一个SQL Server自定义函数,用于从字符串中提取仅包含数字和小数点的子串。该函数通过循环删除非数字字符来实现,并附带创建测试表、存储过程以演示其应用。 ... [详细]
  • 本文介绍了如何在多线程环境中实现异步任务的事务控制,确保任务执行的一致性和可靠性。通过使用计数器和异常标记字段,系统能够准确判断所有异步线程的执行结果,并根据结果决定是否回滚或提交事务。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • PHP 实现多级树形结构:构建无限层级分类系统
    在众多管理系统中,如菜单、分类和部门等模块,通常需要处理层级结构。为了高效管理和展示这些层级数据,本文将介绍如何使用 PHP 实现多级树形结构,并提供代码示例以帮助开发者轻松实现无限分级。 ... [详细]
  • 深入理解Vue.js:从入门到精通
    本文详细介绍了Vue.js的基础知识、安装方法、核心概念及实战案例,帮助开发者全面掌握这一流行的前端框架。 ... [详细]
  • 二叉树的链表实现
    本文介绍了一种使用链表结构表示二叉树的方法。通过定义节点结构和相关操作函数,可以方便地创建、插入和遍历二叉树。 ... [详细]
author-avatar
算错的账目
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有