了解 pinctrl 的数据结构有注意更好的了解 pinctrl 的架构。
1 pinctrl_desc
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
bool link_consumers;
};
pinctrl 子系统通过 pinctrl_desc 结构体为用户提供了描述一个 pin controller 的方法。这也是用户需要根据自己的芯片 pin controller 自己定义的一个变量。
name
pinctrl 的名字,用户自己定义pins
、npins
通过 pins 数组和数组大小 npins 来描述芯片所有的引脚pctlops
提供获取 pin 脚信息的函数,以及 customer 端设备树解析接口pmxops
pin multiplexing 设置相关的函数confops
pin configuration 设置相关的函数num_custom_params
、custom_params
、custom_conf_items
用户自定义的设备节点属性,一般用不到,因为 kernel 默认给我们提供了很丰富的配置项。如下图:
1.1 pinctrl_pin_desc
struct pinctrl_pin_desc {
unsigned number;
const char *name;
void *drv_data;
};
/* Convenience macro to define a single named or anonymous pin descriptor */
#define PINCTRL_PIN(a, b) { .number = a, .name = b }
#define PINCTRL_PIN_ANON(a) { .number = a }
用户要怎么描述一个 pin 脚呢?pinctrl 子系统给了我们现成的一个结构体
number
pin 脚号,从 0 开始且唯一name
pin 脚的名字,如 “PA1”,“GPIO1”等,如果用户不设置名字,则 pinctrl 自动分配名字,如 “PIN0”“PIN1”drv_data
这个一般不用
同时还提供了两个宏定义来赋值:PINCTRL_PIN
、PINCTRL_PIN_ANON
1.2 pinctrl_ops
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 子系统中有一个 group 的概念,就是一个或者多个 pin 组成的一个组。pinctrl 子系统中维护了一个 group 链表,可以认为是一个键值对的 map&#