06、dt_node_to_map 函数分析
设备树里记录了硬件设备的配置信息,比如芯片引脚的功能设置。其中有个叫rockchip_dt_node_to_map的函数,它的作用是:根据设备树里某个硬件节点的描述,自动生成对应的引脚映射表。这个映射表会把芯片引脚的实际物理位置,和它需要实现的功能(比如复用功能或配置参数)对应起来,方便系统直接使用。
一、pinctrl_map
该函数的具体实现在内核源码的“drivers/pinctrl/pinctrl-rock chip.c” 文件中, 在讲解该函数之前需要先对 struct pinctrl_map 结构体进行介绍, 该结构体定义在内核源码的“include/linux/pinctrl/machine.h” 目录下, 具体内容如下所示:
C
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;
};
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
该结构体用于在引脚控制器中定义引脚的映射关系。 通过映射类型的不同, 可以将引脚与具 体 的 复 用 功 能 或 配置信息关联起来 , 从而实现引脚的配 置 和 控 制 。
二、rockchip_dt_node_to_map 函数
然 后 来 看rockchip_dt_node_to_map 函数, 该函数的具体内容如下所示:
C
static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
{
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
const struct rockchip_pin_group *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
int map_num = 1;// 映射数量, 默认为 1
int i;
/*
* first find the group of this node and check if we need to create
* config maps for pins
*/
/* 查找引脚组 */
grp = pinctrl_name_to_group(info, np->name);// 根据节点名称查找对应的引脚组
if (!grp) {
dev_err(info->dev, "unable to find group for node %pOFn\n",
np);
return -EINVAL;
}
map_num += grp->npins;//计算映射数量, 包括复用映射和配置映射
new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);// 分配内存空间用于存储映射数组
if (!new_map)
return -ENOMEM;
*map = new_map;// 将分配的映射数组赋值给输出参数
*num_maps = map_num;// 将映射数量赋值给输出参数
/* 创建复用映射 */
parent = of_get_parent(np);
if (!parent) {
kfree(new_map);
return -EINVAL;
}
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);
/* create config map */
new_map++;
for (i = 0; i < grp->npins; i++) {
new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[i].data.configs.group_or_pin =
pin_get_name(pctldev, grp->pins[i]);
new_map[i].data.configs.configs = grp->data[i].configs;
new_map[i].data.configs.num_configs = grp->data[i].nconfigs;
}
dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
(*map)->data.mux.function, (*map)->data.mux.group, map_num);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
rockchip_dt_node_to_map函数的作用是根据设备树中的节点信息生成对应的引脚映射配置,具体步骤如下:
- 查找引脚组 根据设备节点名称找到对应的引脚组。如果找不到,就报错并返回错误代码EINVAL。
- 计算映射数量 根据引脚组里包含的引脚数量,算出需要创建的映射数量。这些映射分为两种类型:一种是设置引脚功能的「复用映射」,另一种是设置引脚参数的「配置映射」。
- 分配内存 用系统函数申请一块内存空间来存放所有映射数据。如果申请失败,直接返回内存不足的错误代码ENOMEM。
- 返回结果 把生成的映射数组和数量通过参数传递给调用者,完成数据交接。
- 设置复用映射
- 先找到当前设备节点的「父节点」名称,作为复用映射的功能名称。
- 将第一个映射类型标记为「复用组」,数据填入父节点名称,组名填入设备节点名称。
- 释放父节点的引用计数(避免资源泄露)。
- 设置配置映射 遍历引脚组里的每个引脚:
- 每个引脚单独生成一个映射,类型标记为「配置参数」。
- 数据填入引脚名称,同时记录该引脚的具体配置参数(如电平、驱动强度等)。
- 通过系统函数获取引脚的名称。
::: 这个函数通过设备树信息生成两套映射:
复用映射:把引脚组的功能与硬件模块绑定(比如把某个引脚设置为SPI功能)。
配置映射:为每个引脚设置具体的电气参数(如上下拉电阻、信号强度)。 最终这些映射会被引脚控制器用来实际配置硬件,确保设备能正常工作。函数在系统启动时解析设备树时被调用,为硬件初始化做准备。 :::