网站建设 落地页,网站建设 考核指标,快速优化排名公司推荐,人员优化方案pinctrl子系统和gpio子系统虽然难度不大#xff0c;但在内核里的使用率非常高#xff0c;本文争取一次性把相关内容介绍一遍。pinctrl数据结构使用struct pinctrl_desc抽象一个pin controller#xff0c;该结构的定义如下#xff1a;struct pinctrl_desc {const char *name…pinctrl子系统和gpio子系统虽然难度不大但在内核里的使用率非常高本文争取一次性把相关内容介绍一遍。pinctrl数据结构使用struct pinctrl_desc抽象一个pin controller该结构的定义如下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 };pins变量pins和npins把系统中所有的pin描述出来并建立索引。驱动为了和具体的pin对应上再将这些pin组织成一个struct pinctrl_pin_desc类型的数组该类型的定义为struct pinctrl_pin_desc { unsigned number; const char *name; void *drv_data; };pin groupsSoC中有时需要将很多pin组合在一起以实现特定的功能例如uart接口、i2c接口等。因此pin controller需要以group为单位访问、控制多个 pin这就是pin groups。pinctrl core在struct pinctrl_ops中抽象出三个回调函数用来获取pin groups相关信息如下struct pinctrl_ops { //获取系统中pin groups的个数后续的操作将以相应的索引为单位类似数组的下标个数为数组的大小 int (*get_groups_count) (struct pinctrl_dev *pctldev); //获取指定group由索引selector指定的名称 const char *(*get_group_name) (struct pinctrl_dev *pctldev, unsigned selector); //获取指定group的所有pins由索引selector指定结果保存在pins指针数组和num_pins指针中 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); //用于将device tree中的pin state信息转换为pin map 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); };group的组织方式是由驱动决定的。pin configuration除了上面的pin和pin group有些管脚可以配置比如上拉、下拉高阻等。pin configuration来封装这些功能具体体现在struct pinconf_ops数据结构中如下struct pinconf_ops { #ifdef CONFIG_GENERIC_PINCONF bool is_generic; #endif //获取指定 pin 的当前配置保存在 config 指针中 int (*pin_config_get) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config); //设置指定pin的配置 int (*pin_config_set) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, unsigned num_configs); //获取指定pin group的配置项 int (*pin_config_group_get) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config); //设置指定pin group的配置项 int (*pin_config_group_set) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *configs, unsigned num_configs); ......pin mux为了兼容不同的应用场景有很多管脚可以配置为不同的功能例如A和B两个管脚既可以当作普通的GPIO使用又可以配置为I2C的的SCL和SDA也可以配置为UART的TX和RX这称作管脚的复用简称pin mux。使用struct pinmux_ops来抽象pin mux有关的操作如下struct pinmux_ops { //检查某个pin是否已作它用用于管脚复用时的互斥 int (*request) (struct pinctrl_dev *pctldev, unsigned offset); //request的反操作 int (*free) (struct pinctrl_dev *pctldev, unsigned offset); //获取系统中function的个数 int (*get_functions_count) (struct pinctrl_dev *pctldev); //获取指定function的名称 const char *(*get_function_name) (struct pinctrl_dev *pctldev, unsigned selector); //获取指定function所占用的pin group int (*get_function_groups) (struct pinctrl_dev *pctldev, unsigned selector, const char * const **groups, unsigned *num_groups); //将指定的pin groupgroup_selector设置为指定的functionfunc_selector int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector, unsigned group_selector); //以下是gpio相关的操作 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); //为true时说明该pin controller不允许某个pin作为gpio和其它功能同时使用 bool strict; };pin state根据前面的描述pinctrl driver抽象出来了一些离散的对象pinpin group、function、configuration并实现了这些对象的控制和配置方式。然后我们回到某一个具体的device上如 lpuartusdhc。一个设备在某一状态下如工作状态、休眠状态等等所使用的pinpin group、pinpin group的function和configuration是唯一确定的。所以固定的组合可以确定固定的状态在设备树里用pinctrl-names指明状态名字pinctrl-x指明状态引脚。pin mappin state有关的信息是通过pin map收集相关的数据结构如下struct pinctrl_map { //device的名称 const char *dev_name; //pin state的名称 const char *name; //该map的类型 enum pinctrl_map_type type; //pin controller device的名字 const char *ctrl_dev_name; union { struct pinctrl_map_mux mux; struct pinctrl_map_configs configs; } data; }; enum pinctrl_map_type { PIN_MAP_TYPE_INVALID, //不需要任何配置仅仅为了表示state的存在 PIN_MAP_TYPE_DUMMY_STATE, //配置管脚复用 PIN_MAP_TYPE_MUX_GROUP, //配置pin PIN_MAP_TYPE_CONFIGS_PIN, //配置pin group PIN_MAP_TYPE_CONFIGS_GROUP, }; struct pinctrl_map_mux { //group的名字 const char *group; //function的名字 const char *function; }; struct pinctrl_map_configs { //该pin或者pin group的名字 const char *group_or_pin; //configuration数组 unsigned long *configs; //配置项的个数 unsigned num_configs; };pinctrl driver确定了pin map各个字段的格式之后就可以在dts文件中维护pin state以及相应的mapping table。pinctrl core在初始化的时候会读取并解析dts并生成pin map。而各个consumer可以在自己的dts node中直接引用pinctrl driver定义的pin state并在设备驱动的相应的位置调用pinctrl subsystem提供的 APIpinctrl_lookup_statepinctrl_select_stateactive或者deactive这些state。更多内容请看下回。