在上一章我们通过数据结构间的关联,说明了pinctrl子系统的软件框架。本章我们主要介绍每一个数据结构的定义,从而加深对pinctrl子系统相关的数据结构理解。本章我们依然从soc pin描述、board pin描述、设备模型与pinctrl关联三部分进行说明。
在之前两章我们也说明了pinctrl相关的概念,包括pin controller device、pinctrl dev相关的info描述(pinctrl device)、pin引脚描述、function、group等概念。
下面即是这几个数据结构间的关联流程。
该数据结构是soc pin controller的抽象,其包含如下主要信息:
基本上就是这些信息。
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
};
该数据结构是pin ctrl device的info信息描述,定义如下,包含的主要信息:
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
};
这两个数据结构是对应引脚描述的,其中pinctrl_pin_desc描述引脚的名称、引脚index等;而
pin_desc则主要描述该pin当前的配置信息(所属function、group等)、pin引脚配置计数等。定义如下:
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;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
unsigned mux_usecount;
const char *mux_owner;
const struct pinctrl_setting_mux *mux_setting;
const char *gpio_owner;
#endif
};
该数据结构虽然名称是pinctrl_ops,其实主要是对group的操作接口,内容如下:
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);
};
该数据接口主要定义各pinctrl device的引脚复用相关的操作接口,主要内容包含:
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;
};
该接口主要实现一个pinctrl device的引脚配置相关的操作接口,主要内容如下:
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 pin描述相关的数据结构,已经搭建了该soc所支持的pin、function、group以及相关操作接口
等信息;而board pin描述相关的数据结构则描述一块board所使用到的function及相关的group。
而board pin描述主要包含struct pinctrl_maps、struct pinctrl_map这两个数据结构。其中一个
struct pinctrl_map对应一个function,而pinctrl_maps是多个function集合。如下是pinctrl_maps的关联。
该数据结构可以理解为一个function类型,主要内容如下:
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的集合。
上面介绍的soc pin描述、board pin描述,主要介绍了soc支持的引脚数、group数、function数以及操作接口等信息;board pin所使用的function组合、引脚配置等信息。
我们前面介绍在设备与设备驱动match之后的probe函数里才会进行引脚复用以及引脚配置的设置,即设备是引脚配置与引脚复用的持有者,因此设备与pinctrl子系统之间也存在数据结构之间的关联。
如下是设备模型部分与pinctrl子系统相关的数据结构,主要包含struct dev_pin_info、struct pinctrl、struct pinctrl_state、struct pinctrl_setting这几个数据结构,而这些数据结构间的关系则主要根据board pin描述中的struct pinctrl_map等信息建立起来的。
该数据结构表示该device所对应引脚的配置与复用信息,在接口pinctrl_bind_pins中会初始化该设备的dev_pin_info,并进行相应的配置。主要内容如下:
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
};
该数据结构对应一个设备的所有引脚配置相关的信息,该数据结构的定义如下
dev指向拥有该pinctrl的device;
states下链接了该设备支持的所有引脚配置状态;
/**
* struct pinctrl - per-device pin control state holder
* @node: global list node
* @dev: the device using this pin control handle
* @states: a list of states for this device
* @state: the current state
* @dt_maps: the mapping table chunks dynamically parsed from device tree for
* this device, if any
* @users: reference count
*/
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;
};
该数据结构表示设备引脚的一种状态及该状态下的引脚控制信息,如default状态下,包含了设备对应
引脚的复用配置、也包含了设备对应引脚的配置信息。
name表示状态名称;
而链表头settings中则存储了该设备在该状态下的引脚配置信息(这些配置信息以struct pinctrl_setting类型表示);
struct pinctrl_state {
struct list_head node;
const char *name;
struct list_head settings;
};
该数据结构表示一个设备在一个状态下的pinctrl控制信息,包含的内容如下:
type表示控制信息类型(mux group、config group、config pin等类型);
pctrldev指向对应soc pin controller device;
dev_name对应设备名称;
而struct pinctrl_setting_mux表示group的引脚复用配置,这里面包含function index、group index(依据board pin描述中的struct pinctrl_map中的mux的function name、group name、soc pin描述中的function、group信息,火气大到function index、group的index);
而struct pinctrl_setting_configs则包含了group或pin的index,也是借助board pin描述中的group或者pin的name,然后在soc pin描述中查找到对应的group或pin的index。
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的信息,完成该device在每一个state下的引脚配置信息的设置,并完成引脚复用以及引脚配置信息的操作(主要借助函数pinctrl_bind_pins实现);
以上即为pinctrl子系统数据结构的分析,总结如下:
下一章我们介绍具体的函数。