往期内容
本专栏往期内容:
input子系统专栏:
- 专栏地址:input子系统
- input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
– 末片,有往期内容观看顺序I2C子系统专栏:
- 专栏地址:IIC子系统
- 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
– 末篇,有往期内容观看顺序总线和设备树专栏:
- 专栏地址:总线和设备树
- 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
– 末篇,有往期内容观看顺序
前言
在上一篇文章中对Pincontroller进行了简单的介绍(Pinctrl子系统和其主要结构体引入),以及对设备树也进行了示范,对Pincontroller的结构体进行的引入,也就是起了个开头,知道了是用pinctrl_dev
来指代一个Pincontroller,可以提到了可以通过提供一个pinctrl_desc
再去调用某个函数来实现一个pinctrl_dev
。那么接下来就进一步讲解。
那么接下来看看pinctrl_dev --> pinctrl_desc *desc --> pinctrl_ops、pinmux_ops、pinconf_ops
:
1. 作用1:描述、获得引脚 pinctrl_ops
使用pinctrl_ops来操作引脚,主要功能有二:
- 来取出某组的引脚:get_groups_count、get_group_pins
- 处理设备树中pin controller中的某个节点:dt_node_to_map,把device_node转换为一系列的pinctrl_map
\Linux-4.9.88\include\linux\pinctrl\pinctrl.h
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 pinctrl_ops
结构体定义了全局引脚控制操作(pin control operations),这些操作需要由引脚控制器驱动程序实现。该结构体中的函数指针代表不同的操作接口,允许驱动程序通过这些接口与引脚控制子系统进行交互。
get_groups_count
: 返回当前已注册的引脚组(pin group)数量。该函数用于获取系统中引脚组的总数。get_group_name
: 返回特定引脚组的名称。通过组选择器selector
作为参数,驱动可以获取某个引脚组的名称。get_group_pins
: 返回与特定组选择器对应的引脚数组,并通过参数pins
和num_pins
返回该数组的指针和引脚数量。此函数用于查询引脚组包含的具体引脚。pin_dbg_show
: 可选的debugfs
显示挂钩,用于在调试文件系统(debugfs)中展示每个引脚的设备相关信息。它可以在调试时提供关于某个引脚的详细信息。dt_node_to_map
: 解析设备树(Device Tree)中的 “pin 配置节点” 并为其创建映射表项(mapping table entries)。这些映射表项通过map
和num_maps
输出参数返回。该函数是可选的,适用于支持设备树的引脚控制器驱动。dt_free_map
: 释放通过dt_node_to_map
创建的映射表项。顶层的map
指针需要释放,同时还要释放映射表项中动态分配的成员。该函数是可选的,对于不支持设备树的引脚控制器驱动,可以忽略此函数。
这些操作为引脚控制子系统提供了操作引脚组、解析设备树节点、调试显示等功能接口。
2. 作用2:引脚复用 pinmux_ops
把某一组引脚配置成某一功能,GPIO模式??或是其它模式
\Linux-4.9.88\include\linux\pinctrl\pinmux.h
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 pinmux_ops
结构体定义了引脚复用(pinmux)操作,主要用于实现支持引脚复用功能的引脚控制器驱动程序。该结构体提供了一系列回调函数,允许引脚控制器子系统与引脚复用功能进行交互。
request
: 核心功能调用,用于判断特定的引脚是否可以被用于复用。在实际选择复用设置前,核心会调用该函数来请求引脚。驱动程序可以通过返回负值拒绝该请求。free
: 与request()
相反,释放被请求的引脚。这是在引脚复用完成后释放引脚的回调函数。get_functions_count
: 返回当前引脚复用驱动中可选择的复用功能数量。get_function_name
: 根据复用选择器selector
返回某个复用功能的名称。核心通过调用此函数来确定应将某个设备映射到哪个复用设置。get_function_groups
: 根据功能选择器selector
返回与该复用功能相关的引脚组名称数组,并通过groups
和num_groups
返回受影响的组及其数量。可以与pinctrl_ops
中的函数结合使用以获取受影响的引脚。set_mux
: 启用特定的复用功能与引脚组关联。该函数根据func_selector
选择特定的复用功能,并根据group_selector
选择一组引脚进行复用设置。驱动程序不需要检测复用冲突,系统会自动处理引脚冲突。gpio_request_enable
: 请求并启用某个引脚的 GPIO 模式。如果引脚控制器支持每个引脚单独复用为 GPIO 模式,则需要实现此函数。参数包括 GPIO 范围和在该范围内的引脚偏移量。gpio_disable_free
: 释放之前启用的 GPIO 复用设置,与gpio_request_enable
作用相反。gpio_set_direction
: 对于需要引脚复用的 GPIO 控制器,当 GPIO 配置为输入或输出时可能需要不同的设置。该函数允许控制引脚方向(输入或输出)。strict
: 如果为真,则不允许引脚同时作为 GPIO 和复用其他功能使用。在批准引脚请求之前,会严格检查gpio_owner
和mux_owner
以防止冲突。
pinmux_ops
提供了驱动与引脚复用子系统之间的交互接口,用于管理引脚复用、GPIO 配置、引脚组和功能的分配。
3. 作用3:引脚配置 pinconf_ops
上拉?下拉?等等
\Linux-4.9.88\include\linux\pinctrl\pinconf.h
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);
int (*pin_config_dbg_parse_modify) (struct pinctrl_dev *pctldev,
const char *arg,
unsigned long *config);
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);
};
struct pinconf_ops
结构体定义了引脚配置操作,用于支持引脚配置功能的驱动程序实现。它包含一系列函数指针,这些函数用于获取和设置单个引脚及引脚组的配置。
is_generic
: (可选)如果引脚控制器希望使用通用接口,设置该标志以告诉框架其为通用接口。pin_config_get
: 获取特定引脚的配置。如果请求的配置在该控制器上不可用,返回-ENOTSUPP
;如果可用但被禁用,返回-EINVAL
。pin_config_set
: 配置单个引脚的设置。该函数接受引脚的配置参数和数量,允许驱动程序在特定引脚上设置多个配置。pin_config_group_get
: 获取特定引脚组的配置。该函数通过选择器返回整个引脚组的配置,便于一次性读取多个引脚的设置。pin_config_group_set
: 配置引脚组内所有引脚的设置。与pin_config_set
类似,但作用于整个引脚组。pin_config_dbg_parse_modify
: (可选)用于调试文件系统的功能,允许修改引脚配置。pin_config_dbg_show
: (可选)调试文件系统中的显示钩子,提供特定引脚的设备信息。pin_config_group_dbg_show
: (可选)调试文件系统中的显示钩子,提供特定引脚组的设备信息。pin_config_config_dbg_show
: (可选)调试文件系统中的显示钩子,解码并显示驱动程序的引脚配置参数。
4. 使用pinctrl_desc注册得到pinctrl_dev
分析的文件: