在前文我们已经介绍了pinctrl子系统的软件框架及各数据结构之间的关联。本章将进一步深入探讨每个核心数据结构的定义和作用,以加深对pinctrl子系统架构的理解。
我们将从SOC引脚描述、板级引脚描述以及设备模型与pinctrl子系统的关联三个方面进行详细说明。
SOC引脚描述相关数据结构
在之前的文章中,我们讨论了pinctrl子系统的基本概念,包括pin控制器设备(pin controller device)、pinctrl设备描述信息(pinctrl dev info)、引脚描述、功能(function)和组(group)等。
- PIN控制器设备抽象为struct pinctrl_dev,表示一个SOC上的PIN控制器。
- pinctrl dev info对应的数据结构是struct pinctrl_desc,它包含支持的引脚定义、配置接口、复用接口和组操作接口。
- 复用接口由struct pinmux_ops定义,提供了如申请、释放引脚、设置复用等功能。
- 组操作接口由struct pinctrl_ops定义,用于获取组的数量、名称及对应的引脚信息。
- 功能操作接口由struct pinconf_ops定义,用于设置和获取引脚配置。
- 针对每个引脚有struct pinctrl_pin_desc和struct pin_desc两个结构体,前者描述引脚名称和ID,后者记录引脚使用计数、当前所属的功能和组信息。
以下是这些数据结构之间的关联流程:
struct pinctrl_dev
该结构体是SOC PIN控制器的抽象,主要包含以下信息:
- struct pinctrl_desc类型的变量desc,描述pinctrl设备的信息。
- 基数树pin_desc_tree用于存储引脚使用情况,判断引脚是否被多次配置。
- 基数树pin_group_tree和pin_function_tree用于存储组和功能的描述信息。
- gpio_ranges链接GPIO范围到PIN范围的相关信息。
- 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设备的信息,主要包括:
- 所有引脚的描述信息(struct pinctrl_pin_desc *pins)和引脚数量。
- 引脚复用的操作接口(struct pinmux_ops *pmxops)。
- 引脚配置的操作接口(struct pinconf_ops *confops)。
- 组信息获取的操作接口(struct pinctrl_ops *pctlops)。
- 通用属性参数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
该结构体主要提供组操作接口:
- get_groups_count:获取组的数量。
- get_group_name:根据ID获取组名。
- 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
该结构体定义了引脚复用相关的操作接口:
- request/free:申请或释放引脚。
- get_functions_count:获取所有功能的数量。
- get_function_name:根据ID获取功能名。
- get_function_groups:获取功能关联的组。
- set_mux:设置引脚复用。
- 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
该结构体实现引脚配置相关的操作接口:
- pin_config_get:获取引脚配置。
- pin_config_set:设置引脚配置。
- pin_config_group_get:获取组配置。
- 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
该结构体描述了一个功能类型,主要内容包括:
- dev_name:设备名称。
- name:状态名称(如default、idle、sleep)。
- type:pinctrl_map类型(如mux group、config group等)。
- ctrl_dev_name:pinctrl设备名称。
- 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
该结构体描述设备的引脚配置与复用信息,主要内容包括:
- struct pinctrl类型的变量,表示支持的引脚配置状态。
- default_state:默认状态。
- init_state:初始化状态。
- 若支持电源管理,则还包括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信息,完成设备在每个状态下的引脚配置信息的设置,并实现引脚复用和配置操作。
总结:
- SOC引脚描述涵盖了所有支持的引脚、功能、组及相关操作接口。
- 板级引脚描述选择了SOC引脚描述中的一个子集。
- 设备模型与pinctrl关联部分根据设备相关的pinctrl map信息确定了所有状态下所对应的mux、group/pin config信息,并依据当前状态进行配置。
下一章我们将介绍具体的函数实现。