基于MainLine Kernel(6.15-rc1) Pinctrl子系统
一、基本数据结构
1. pinctroller
pinctrl_dev 与 pinctrl_desc
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 {
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;
};
我们进入到驱动目录里 drivers\pinctrl\freescale\pinctrl-imx.c 的 .probe函数
int imx_pinctrl_probe(struct platform_device *pdev,
const struct imx_pinctrl_soc_info *info)
{
struct regmap_config config = { .name = "gpr" };
struct device_node *dev_np = pdev->dev.of_node;
struct pinctrl_desc *imx_pinctrl_desc;
struct device_node *np;
struct imx_pinctrl *ipctl;
struct regmap *gpr;
int ret, i;
...
imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
imx_pinctrl_desc->pmxops = &imx_pmx_ops;
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
...
}
其中比较重要的,struct pctlops 、struct pmxops,pinconf_ops,我们看看他们的结构体时怎么构造的
struct pinctrl_ops {
int (*get_groups_count) (struct pinctrl_dev *pctldev);
const char *(*get_group_name) (struct pinctrl_dev *pctldev,
unsigned int selector);
int (*get_group_pins) (struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins);
void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int offset);
int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned int *num_maps);
void (*dt_free_map) (struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned int num_maps);
};
##################################
struct pinmux_ops {
int (*request) (struct pinctrl_dev *pctldev, unsigned int offset);
int (*free) (struct pinctrl_dev *pctldev, unsigned int offset);
int (*get_functions_count) (struct pinctrl_dev *pctldev);
const char *(*get_function_name) (struct pinctrl_dev *pctldev,
unsigned int selector);
int (*get_function_groups) (struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int *num_groups);
int (*set_mux) (struct pinctrl_dev *pctldev, unsigned int func_selector,
unsigned int group_selector);
int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset);
.....
};
#############################################
struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF
bool is_generic;
#endif
int (*pin_config_get) (struct pinctrl_dev *pctldev,
unsigned int pin,
unsigned long *config);
int (*pin_config_set) (struct pinctrl_dev *pctldev,
unsigned int pin,
unsigned long *configs,
unsigned int num_configs);
int (*pin_config_group_get) (struct pinctrl_dev *pctldev,
unsigned int selector,
unsigned long *config);
int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
unsigned int selector,
unsigned long *configs,
unsigned int num_configs);
...
};
首先来解释为什么要有 pinctrl_ops 这么一个结构体呢?我们可以看到 struct pinctrl_desc 里有这么两个属性
const struct pinctrl_pin_desc *pins;
unsigned int npins;
struct pinctrl_pin_desc {
unsigned int number;
const char *name;
void *drv_data;
};
这两个属性都是用来描述单个引脚的,而看 pinctrl_ops 提供的函数,可以获得多个group里的pin信息(提供 groups、pins、group和pin之间的组织关系)。
然后再来看 pinmux_ops 结构体,比较重要的函数就是他就是set_mux(),来把 pinctrl_ops 获取 的 描述信息去设置mux寄存器(复用为什么功能,GPIO、UART、SPI之类)。
可以理解为:
驱动请求(pinctrl_select_state)
↓
根据设备树找 pinctrl state
↓
根据 pctlops 描述,找到对应的 group(s)
↓
调用 pmxops->set_mux,把 pins 设置到正确的功能
最后就是 pinconf_ops ,它的作用是配置 pin 的电气属性(上拉、下拉、驱动强度等)。
以上就是pinctroller端的基本数据结构.
2.注册函数
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct device *dev, void *driver_data);
可以看到参数是一个 struct pinctrl_desc,而返回值是 struct pinctrl_dev,以后就用 pinctrl_dev 来描述一个 pincontroller。
pinctrl_flexcan1: flexcan1grp {
fsl,pins = <
MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
>;
};
上面分析的数据结构都是来描述这个 pincontroller.
4.pinctrl client
但是我们在使用中还有一个client,这部分是怎么描述的?
先看在dtb中的编写:通过 pinctrl-names 的属性来选择 pin要配置为什么模式。
device {
pinctrl-names = "default","sleep";
pinctrl-0 = <&pinctrl_device0>;
pinctrl-1 = <&pinctrl_device1>;
};
首先设备树会被编译成 platform_device结构体(不全是,比如i2c_client),但是里面都会有一个 device 结构体。
struct platform_device {
const char *name;
int id;
bool id_auto;
struct device dev; 《--------------
u64 platform_dma_mask;
....
};
struct i2c_client {
...
struct i2c_adapter *adapter; /* the adapter we sit on */
struct device dev; /* the device structure */ 《--------------
int init_irq; /* irq set at initialization */
int irq; /* irq issued by device */
struct list_head detected;
...
};
所以不管被编译为什么结构体,最终都汇聚到这个 struct device 来和 pinctrl 挂钩。
struct device {
...
void *platform_data; /* Platform specific data, device
core doesn't touch it */
void *driver_data; /* Driver data, set and get with
dev_set_drvdata/dev_get_drvdata */
struct mutex mutex; /* mutex to synchronize calls to
* its driver.
*/
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins; <-------------------------
#endif
struct dev_msi_info msi;
#ifdef CONFIG_ARCH_HAS_DMA_OPS
const
...
}
就是通过 struct dev_pin_info *pins 和 pinctrl 挂钩的。
4.1struct dev_pin_info
这个结构体只在需要使用pinctrl 子系统时构造。
可以看出这几个 pinctrl_state 结构体都是由 dtb中的 pinctrl client 的 pinctrl-names 属性构造的。
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
};
4.2自定义状态
则都是几种常用的状态,那么有没有方法让我们自定义状态呢?
有的兄弟,有的。
我们自定义的状态会放在 struct pinctrl *p 里的 struct list_head states 链表里,(关于解析部分之后分析)。
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;
};
4.3pinctrl_map 和 pinctrl_setting
当我们的pinctrl cliend 想要去使用pinctrl,是通过 struct dev_pin_info 去建立联系的,那么我们 pinctroller 的设备节点也得需要去保存到这个结构体里。
还记得 pctlops 吗,就是它来解析的,它是来处理一组引脚的。这个结构体里有一个函数 dt_node_to_map().
int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned int *num_maps);
就是来把设备树节点转换为一系列的 pinctrl_map 结构体。
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_map —> struct pinctrl_setting ,去配置这些引脚的功能。
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 pinctrl_state {
struct list_head node;
const char *name;
struct list_head settings;
};
这个 struct pinctrl_setting又存放在 pinctrl_state.settings里,以后让这个设备位于某个状态时,就会根据这些 .settings来设置引脚。
(map —>setting 这部分是内核的工作,想了解可以查看 drivers\pinctrl\core.c)
pinctrl_get()
create_pinctrl()
pinctrl_dt_to_map()
add_setting()
4.4操作流程
看一下怎么来根据 .setting 来设置引脚的,进入内核目录 drivers\base\dd.c,查看 really_probe() 函数。
static int really_probe(struct device *dev, const struct device_driver *drv)
{
bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) &&
!drv->suppress_bind_attrs;
int ret, link_ret;
...
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev); <-----------------
if (ret)
goto pinctrl_bind_failed;
}
会看到有一个 pinctrl_bind_pins(),进入查看
int pinctrl_bind_pins(struct device *dev)
{
...
if (IS_ERR(dev->pins->init_state)) {
/* Not supplying this state is perfectly legal */
dev_dbg(dev, "no init pinctrl state\n");
ret = pinctrl_select_state(dev->pins->p,
dev->pins->default_state);
} else {
ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state);
}
...
}
找到一个选择状态函数 pinctrl_select_state(),接着进入
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
{
if (p->state == state)
return 0;
return pinctrl_commit_state(p, state); <-------------
}
这里会判断一下初始化的状态是否正常,接着进入 pinctrl_commit_state().
static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
{
struct pinctrl_setting *setting;
struct pinctrl_state *old_state = READ_ONCE(p->state);
int ret;
...
/* Apply all the settings for the new state - pinmux first */
list_for_each_entry(setting, &state->settings, node) { <-------------
switch (setting->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_enable_setting(setting);
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = 0; //跳过
break;
default:
ret = -EINVAL;
break;
}
if (ret < 0)
goto unapply_new_state;
/* Do not link hogs (circular dependency) */
if (p != setting->pctldev->p)
pinctrl_link_add(setting->pctldev, p->dev);
}
/* Apply all the settings for the new state - pinconf after */
list_for_each_entry(setting, &state->settings, node) { <-------------
switch (setting->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = 0; // mux 已完成,跳过
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = pinconf_apply_setting(setting);
break;
default:
ret = -EINVAL;
break;
}
...
}
有两个switch 语句,这样分布的机制就是为了保证在做 config 设置前,引脚已经正确映射到目标功能(比如 UART1_TX),否则如果 pin 还处于 GPIO 模式,你设置电平、上拉下拉等都没有意义。
根据 setting->type 来执行相应的配置函数,对于mux部分执行 pinmux_enable_setting(),最终调用到了 set_mux 函数来配置引脚的复用。
int pinmux_enable_setting(const struct pinctrl_setting *setting)
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
...
ret = ops->set_mux(pctldev, setting->data.mux.func,
setting->data.mux.group);
...
}
对于 config 部分执行 pinconf_apply_setting(),最终调用到了 pin_config_group_set().
int pinconf_apply_setting(const struct pinctrl_setting *setting)
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinconf_ops *ops = pctldev->desc->confops;
int ret;
...
ret = ops->pin_config_group_set(pctldev,
setting->data.configs.group_or_pin,
setting->data.configs.configs,
setting->data.configs.num_configs);
...
}
根据之前在.probe 分配注册的函数,就是在这里被执行的.
二、DTB解析
1.pincontroller
3.1首先是描述、获得引脚
打开内核源码目录 drivers\pinctrl\freescale\pinctrl-imx6ul.c
static const struct of_device_id imx6ul_pinctrl_of_match[] = {
{ .compatible = "fsl,imx6ul-iomuxc", .data = &imx6ul_pinctrl_info, },
{ .compatible = "fsl,imx6ull-iomuxc-snvs", .data = &imx6ull_snvs_pinctrl_info, },
{ /* sentinel */ }
};
static struct platform_driver imx6ul_pinctrl_driver = {
.driver = {
.name = "imx6ul-pinctrl",
.of_match_table = imx6ul_pinctrl_of_match,
.suppress_bind_attrs = true,
},
.probe = imx6ul_pinctrl_probe,
};
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{
const struct imx_pinctrl_soc_info *pinctrl_info;
pinctrl_info = of_device_get_match_data(&pdev->dev);
if (!pinctrl_info)
return -ENODEV;
return imx_pinctrl_probe(pdev, pinctrl_info);
}
可以看到 platform_driver 支持 “fsl,imx6ul-iomuxc”、"fsl,imx6ull-iomuxc-snvs"这两个平台设备,然后再probe函数调用 imx_pinctrl_probe
进入到 imx_pinctrl_probe(pdev, pinctrl_info)
int imx_pinctrl_probe(struct platform_device *pdev,
const struct imx_pinctrl_soc_info *info)
{
struct regmap_config config = { .name = "gpr" };
struct device_node *dev_np = pdev->dev.of_node;
struct pinctrl_desc *imx_pinctrl_desc;
struct device_node *np;
struct imx_pinctrl *ipctl;
struct regmap *gpr;
int ret, i;
...
imx_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*imx_pinctrl_desc),
GFP_KERNEL);
if (!imx_pinctrl_desc)
return -ENOMEM;
imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
imx_pinctrl_desc->pmxops = &imx_pmx_ops;
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
...
...
ret = imx_pinctrl_probe_dt(pdev, ipctl);
...
}
看重点,这里就是在构造一个 pinctrl_desc 的结构体。
那么引脚是怎么获得的呢?
3.2解析设备树
进入 imx_pinctrl_probe_dt()
static int imx_pinctrl_probe_dt(struct platform_device *pdev,
struct imx_pinctrl *ipctl)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
struct pinctrl_dev *pctl = ipctl->pctl;
u32 nfuncs = 0;
u32 i = 0;
bool flat_funcs;
if (!np)
return -ENODEV;
/* 判断设备树结构是不是 flat 模式 */
flat_funcs = imx_pinctrl_dt_is_flat_functions(np);
if (flat_funcs) {
nfuncs = 1;
} else {
/* 获得有多少个function (多少个子节点) */
nfuncs = of_get_child_count(np);
if (nfuncs == 0) {
dev_err(&pdev->dev, "no functions defined\n");
return -EINVAL;
}
}
/* 对于每一个function(子节点) 都会去分配一个 function_desc 结构体*/
for (i = 0; i < nfuncs; i++) {
struct function_desc *function;
function = devm_kzalloc(&pdev->dev, sizeof(*function),
GFP_KERNEL);
if (!function)
return -ENOMEM;
mutex_lock(&ipctl->mutex);
radix_tree_insert(&pctl->pin_function_tree, i, function);
mutex_unlock(&ipctl->mutex);
}
pctl->num_functions = nfuncs;
ipctl->group_index = 0;
if (flat_funcs) {
pctl->num_groups = of_get_child_count(np);
} else {
pctl->num_groups = 0;
for_each_child_of_node(np, child)
/* 计算子function下又有多少个group(子节点)*/
pctl->num_groups += of_get_child_count(child);
}
if (flat_funcs) {
imx_pinctrl_parse_functions(np, ipctl, 0);
} else {
i = 0;
for_each_child_of_node(np, child)
imx_pinctrl_parse_functions(child, ipctl, i++);
}
return 0;
}
最终调用 imx_pinctrl_parse_functions()
,从设备树中提取每个 function 下的 group 和 pins,解析结构体并缓存。
补充:这里多次判断了 flat_funcs 这个值,设备树有两种组织形式:
(1)Flat 模式:所有 group 都直接定义在顶层 iomuxc 节点下
pinctrl@20e0000 {
pinctrl_uart1: uart1grp {
fsl,pins = <...>;
};
pinctrl_i2c1: i2c1grp {
fsl,pins = <...>;
};
};
(2)Function 分组模式(非 flat):顶层为 function,function 下再分 group
pinctrl@20e0000 {
uart1 {
uart1grp {
fsl,pins = <...>;
};
};
i2c1 {
i2c1grp {
fsl,pins = <...>;
};
};
};
接着来看具体怎么解析的,首先是 function
static int imx_pinctrl_parse_functions(struct device_node *np,
struct imx_pinctrl *ipctl,
u32 index)
{
struct pinctrl_dev *pctl = ipctl->pctl;
struct function_desc *func;
struct group_desc *grp;
const char **group_names;
u32 i;
dev_dbg(pctl->dev, "parse function(%d): %pOFn\n", index, np);
func = pinmux_generic_get_function(pctl, index);
if (!func)
return -EINVAL;
/* Initialise function */
/* 设置为设备树 function 节点名 */
func->func.name = np->name;
/* 该 function 下有几个 group */
func->func.ngroups = of_get_child_count(np);
if (func->func.ngroups == 0) {
dev_info(ipctl->dev, "no groups defined in %pOF\n", np);
return -EINVAL;
}
/* 分配 group 名称数组,稍后填入所有 group 的名字 */
group_names = devm_kcalloc(ipctl->dev, func->func.ngroups,
sizeof(*func->func.groups), GFP_KERNEL);
if (!group_names)
return -ENOMEM;
i = 0;
/* 将每个子 group 的名字填入 groups 数组,用于 framework 调用 pinmux_enable_setting() 时识别 group */
for_each_child_of_node_scoped(np, child)
group_names[i++] = child->name;
func->func.groups = group_names;
i = 0;
/* 遍历每个 group,注册到 pinctrl */
for_each_child_of_node_scoped(np, child) {
grp = devm_kzalloc(ipctl->dev, sizeof(*grp), GFP_KERNEL);
if (!grp)
return -ENOMEM;
mutex_lock(&ipctl->mutex);
radix_tree_insert(&pctl->pin_group_tree,
ipctl->group_index++, grp);
mutex_unlock(&ipctl->mutex);
/* 进一步解析 fsl,pins 属性 */
imx_pinctrl_parse_groups(child, grp, ipctl, i++);
}
return 0;
}
对于每个 function 都会解析成一个 function_desc 结构体
struct function_desc {
struct pinfunction func;
void *data;
};
struct pinfunction {
const char *name;
const char * const *groups;
size_t ngroups;
};
然后再通过 imx_pinctrl_parse_groups() 将每个group 解析为一个 group_desc 结构体
struct group_desc {
struct pingroup grp;
void *data;
};
struct pingroup {
const char *name;
const unsigned int *pins;
size_t npins;
};
进入imx_pinctrl_parse_groups()
static int imx_pinctrl_parse_groups(struct device_node *np,
struct group_desc *grp,
struct imx_pinctrl *ipctl,
u32 index)
{
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pin *pin;
unsigned int *pins;
int size, pin_size;
const __be32 *list;
int i;
...
for (i = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i];
if (info->flags & IMX_USE_SCU)
info->imx_pinctrl_parse_pin(ipctl, &pins[i], pin, &list);
else
/* 解析单个引脚 */
imx_pinctrl_parse_pin_mmio(ipctl, &pins[i], pin, &list, np);
}
}
这里又出现一个 struct imx_pin ,因为不管这一组group里有多少个pin,最终都是一个一个来解析的。
struct imx_pin {
unsigned int pin;
union {
struct imx_pin_mmio mmio;
struct imx_pin_scu scu;
} conf;
};
进入 imx_pinctrl_parse_pin_mmio()
static void imx_pinctrl_parse_pin_mmio(struct imx_pinctrl *ipctl,
unsigned int *pin_id, struct imx_pin *pin,
const __be32 **list_p,
struct device_node *np)
{
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pin_mmio *pin_mmio = &pin->conf.mmio;
struct imx_pin_reg *pin_reg;
const __be32 *list = *list_p;
u32 mux_reg, conf_reg;
u32 config;
mux_reg = be32_to_cpu(*list++);
if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
mux_reg = -1;
if (info->flags & SHARE_MUX_CONF_REG) {
conf_reg = mux_reg;
} else {
conf_reg = be32_to_cpu(*list++);
if (!conf_reg)
conf_reg = -1;
}
*pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
pin_reg = &ipctl->pin_regs[*pin_id];
pin->pin = *pin_id;
pin_reg->mux_reg = mux_reg;
pin_reg->conf_reg = conf_reg;
pin_mmio->input_reg = be32_to_cpu(*list++);
pin_mmio->mux_mode = be32_to_cpu(*list++);
pin_mmio->input_val = be32_to_cpu(*list++);
config = be32_to_cpu(*list++);
/* SION bit is in mux register */
if (config & IMX_PAD_SION)
pin_mmio->mux_mode |= IOMUXC_CONFIG_SION;
pin_mmio->config = config & ~IMX_PAD_SION;
*list_p = list;
dev_dbg(ipctl->dev, "%s: 0x%x 0x%08lx", info->pins[*pin_id].name,
pin_mmio->mux_mode, pin_mmio->config);
}
这里可以清楚的看到,就是根据设备树的信息来记录寄存器的值,这些信息到保存到了 struct imx_pin_mmio 里。
三、pinctrl cliend使用过程
只要它是一个设备,那么就会和一个相对应的驱动去匹配,在匹配之前会调用一个 really_probe().
static int really_probe(struct device *dev, const struct device_driver *drv)
{
...
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
...
}
int pinctrl_bind_pins(struct device *dev)
{
/* 上面提到的map to setting */
dev->pins->p = devm_pinctrl_get(dev); <------------------------------
if (IS_ERR(dev->pins->p)) {
dev_dbg(dev, "no pinctrl handle\n");
ret = PTR_ERR(dev->pins->p);
goto cleanup_alloc;
}
dev->pins->init_state = pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_INIT);
if (IS_ERR(dev->pins->init_state)) {
/* Not supplying this state is perfectly legal */
dev_dbg(dev, "no init pinctrl state\n");
/* 需要在转换之后去使用 */
ret = pinctrl_select_state(dev->pins->p, <------------------------------
dev->pins->default_state);
} else {
ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state);
}
...
}
进入 pinctrl_select_state()
pinctrl_select_state()
pinctrl_commit_state()
static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
{
...
/* Apply all the settings for the new state - pinmux first */
list_for_each_entry(setting, &state->settings, node) {
switch (setting->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_enable_setting(setting);
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = 0;
break;
default:
ret = -EINVAL;
break;
}
/* Apply all the settings for the new state - pinconf after */
list_for_each_entry(setting, &state->settings, node) {
switch (setting->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = 0;
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = pinconf_apply_setting(setting);
break;
default:
ret = -EINVAL;
break;
}
...
}
这个宏定义在哪里被设置的呢?
就是在最开始的 dt_node_to_map()里
static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
{
...
new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
new_map[0].data.mux.function = parent->name;
new_map[0].data.mux.group = np->name;
of_node_put(parent);
new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[j].data.configs.group_or_pin =
pin_get_name(pctldev, pin->pin);
...
}