RK3568驱动指南|第十一篇 pinctrl 子系统-第123章dt_node_to_map函数分析

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十一篇 pinctrl 子系统_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第123章dt_node_to_map函数分析

设备树(Device Tree)中存放的是对硬件设备信息的描述,包含了硬件设备的配置和连接信息,例如在pinctrl节点中的引脚的配置和映射关系。而rockchip_dt_node_to_map 函数的作用就是根据设备树中的节点信息,生成对应的引脚映射数组。这个映射数组将描述硬件功能(如复用功能和配置信息)与设备树中的引脚信息进行绑定。

dt_node_to_map函数已经在122.4.1小节的pinctrl_ops函数操作集中进行了简单的讲解,现在将对该函数进行详细的介绍。该函数的具体实现在内核源码的“drivers/pinctrl/pinctrl-rockchip.c”文件中,在讲解该函数之前需要先对struct pinctrl_map结构体进行介绍,该结构体定义在内核源码的“include/linux/pinctrl/machine.h”目录下,具体内容如下所示:

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;
};

该结构体用于在引脚控制器中定义引脚的映射关系。通过映射类型的不同,可以将引脚与具体的复用功能或配置信息关联起来,从而实现引脚的配置和控制。然后来看rockchip_dt_node_to_map函数,该函数的具体内容如下所示:

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 device *dev = info->dev; // 设备指针
	struct pinctrl_map *new_map; // 新的引脚映射数组
	struct device_node *parent; // 父节点指针
	int map_num = 1; // 映射数量,默认为1
	int i;

	/* 查找引脚组 */
	grp = pinctrl_name_to_group(info, np->name); // 根据节点名称查找对应的引脚组
	if (!grp) {
		dev_err(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); // 释放父节点的引用计数

	/* 创建配置映射 */
	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(dev, "maps: function %s group %s num %d\n",
		(*map)->data.mux.function, (*map)->data.mux.group, map_num); // 打印调试信息,显示创建的引脚映射的功能名称、组名和数量

	return 0; // 返回成功标志
}

第14-20行:函数根据设备节点的名称使用pinctrl_name_to_group函数查找与该节点对应的引脚组。如果找不到引脚组,则函数打印错误消息并返回EINVAL错误代码。

第22行:函数根据引脚组的引脚数量计算需要创建的映射数量。映射数量包括复用映射和配置映射。

第24-26行:函数使用kcalloc函数为映射数组(new_map)分配内存空间。分配的大小为映射数量乘以每个映射的大小。如果内存分配失败,函数将返回ENOMEM错误代码。

第28-29行:函数将分配的映射数组(new_map)和映射数量(map_num)通过输出参数map和num_maps返回给调用者。

第31-40行:函数首先获取设备节点的父节点,并将其作为复用映射的功能名称。然后,函数设置第一个映射的类型为PIN_MAP_TYPE_MUX_GROUP,并将父节点的名称作为映射的数据。同时,将设备节点的名称作为映射的组名。最后,函数使用of_node_put释放父节点的引用计数。

第42-52行:函数遍历引脚组的引脚数组,并为每个引脚创建一个配置映射。函数设置映射的类型为PIN_MAP_TYPE_CONFIGS_PIN,并将引脚的名称作为映射的数据。同时,将引脚组中该引脚的配置信息和配置数量设置为映射的配置数据。函数使用pin_get_name函数获取引脚的名称。

rockchip_dt_node_to_map函数根据设备节点的信息创建引脚映射,包括复用映射和配置映射。复用映射用于将引脚组的功能与父节点的功能关联起来,而配置映射用于将引脚的配置信息与引脚的名称关联起来。这些映射将用于配置引脚控制器,以确保引脚在系统中正确地配置和使用。这个函数在设备树解析过程中被调用,以便为每个设备节点创建相应的引脚映射。

到这里关于pinctrl子系统第一阶段的讲解到这里就结束了,为了帮助大家整合讲解过的知识点,作者绘制了以下思维导图:

注:该思维导图的存放路径为iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\05_思维导图\01_pinctrl 阶段1.jpg

图 123-1

大家可以根据该思维导图,对上面章节的内容进行梳理,从而真正理解pinctrl子系统框架。

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值