pinctl_map:引脚三千,只取一瓢

pinctl_map:引脚三千,只取一瓢

总体框图:
在这里插入图片描述

pinctrl_map数组
  • pin group配置信息

    • pinctrl_map[0]:配置pin group的所有引脚复用

    • pinctrl_map[1~n]:配置pin group的每个引脚的属性

函数层次分析

pinctrl_enable()->pinctrl_claim_hogs()

  • create_pinctrl

    ----------------------------------------------第一部分-------------------------------------

    • pinctrl_dt_to_map()

      • for (state = 0; ; state++):查找外设所有pin group的状态

        • for (config = 0; config < size; config++):查找状态的所有引脚组

          ------------------------------第二部分-------------------------------------

          • dt_to_map_one_config

            • 创建一个pinctrl_map,负责初始化配置pin group的所有引脚复用

            • 创建多个pinctrl_map,每个pinctrl_map负责配置引脚中的一个引脚属性

    ----------------------------------------------第三部分-------------------------------------

    • add_setting
imx_dt_node_to_map()函数

drivers/pinctrl/freescale/pinctrl-imx.c

参数:ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);

np_config–指获取到的子节点

static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
			struct device_node *np,
			struct pinctrl_map **map, unsigned *num_maps)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct group_desc *grp;
	struct pinctrl_map *new_map;
	struct device_node *parent;
	int map_num = 1;
	int i, j;
	//去查找基数树里存储的group_desc指针
	grp = imx_pinctrl_find_group_by_name(pctldev, np->name);
	
	if (info->flags & IMX8_USE_SCU) {
		map_num += grp->num_pins;
	} else {
		for (i = 0; i < grp->num_pins; i++) {
			struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];

			if (!(pin->pin_conf.pin_memmap.config & IMX_NO_PAD_CTL))
				map_num++;
		}
	}
	
	new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
				GFP_KERNEL);
				
	*map = new_map;
	*num_maps = map_num;
	
	 /*iomuxc节点*/
	 parent = of_get_parent(np);
	 ...
	 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;
	 ..
	 new_map++;
	 
	 for (i = j = 0; i < grp->num_pins; i++) {
		struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];

		if (info->flags & IMX8_USE_SCU) {
			new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
			new_map[j].data.configs.group_or_pin =
					pin_get_name(pctldev, pin->pin);
			new_map[j].data.configs.configs =
					(unsigned long *)&pin->pin_conf.pin_scu;
			new_map[j].data.configs.num_configs = 2;
			j++;
		} else if (!(pin->pin_conf.pin_memmap.config & IMX_NO_PAD_CTL)) {
			new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
			new_map[j].data.configs.group_or_pin =
					pin_get_name(pctldev, pin->pin);
			new_map[j].data.configs.configs =
					&pin->pin_conf.pin_memmap.config;
			new_map[j].data.configs.num_configs = 1;
			j++;
		}
	}
	...
}
imx_pinctrl_find_group_by_name()函数
static inline const struct group_desc *imx_pinctrl_find_group_by_name(
				struct pinctrl_dev *pctldev,
				const char *name)
{
	const struct group_desc *grp = NULL;
	int i;

	for (i = 0; i < pctldev->num_groups; i++) {
        //去查找基数树里存储的group_desc指针
		grp = pinctrl_generic_get_group(pctldev, i);
		if (grp && !strcmp(grp->name, name)) //判断是否为空
			break;
	}

	return grp;
}
pinctrl_generic_get_group()函数

drivers/pinctrl/core.c

struct group_desc *pinctrl_generic_get_group(struct pinctrl_dev *pctldev,
					     unsigned int selector)
{
	struct group_desc *group;

	group = radix_tree_lookup(&pctldev->pin_group_tree,
				  selector);
	if (!group)
		return NULL;

	return group;
}
pin_get_name()函数

drivers/pinctrl/core.c

const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
{
	const struct pin_desc *desc;

	desc = pin_desc_get(pctldev, pin);
	if (!desc) {
		dev_err(pctldev->dev, "failed to get pin(%d) name\n",
			pin);
		return NULL;
	}

	return desc->name;
}
pin_desc_get函数

drivers/pinctrl/core.h

static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
					    unsigned int pin)
{
	return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
}
dt_remember_or_free_map()函数

drivers/pinctrl/devicetree.c

static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,struct pinctrl_dev *pctldev,struct pinctrl_map *map, unsigned num_maps)
{
	int i;
	struct pinctrl_dt_map *dt_map;

	/* Initialize common mapping table entry fields */
	for (i = 0; i < num_maps; i++) {
		map[i].dev_name = dev_name(p->dev);
		map[i].name = statename;
		if (pctldev)
			map[i].ctrl_dev_name = dev_name(pctldev->dev);
	}

	/* Remember the converted mapping table entries */
	dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
	if (!dt_map) {
		dt_free_map(pctldev, map, num_maps);
		return -ENOMEM;
	}

	dt_map->pctldev = pctldev;
	dt_map->map = map;
	dt_map->num_maps = num_maps;
	list_add_tail(&dt_map->node, &p->dt_maps);

	return pinctrl_register_map(map, num_maps, false);
}
pinctrl_register_map()函数

drivers/pinctrl/core.c

int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
			 bool dup)
{
	int i, ret;
	struct pinctrl_maps *maps_node;
	
	for (i = 0; i < num_maps; i++) {
	
	switch (maps[i].type) {
		case PIN_MAP_TYPE_DUMMY_STATE:
			break;
		case PIN_MAP_TYPE_MUX_GROUP:
			ret = pinmux_validate_map(&maps[i], i);
			if (ret < 0)
				return ret;
			break;
		case PIN_MAP_TYPE_CONFIGS_PIN:
		case PIN_MAP_TYPE_CONFIGS_GROUP:
			ret = pinconf_validate_map(&maps[i], i);
			if (ret < 0)
				return ret;
			break;
		default:
			pr_err("failed to register map %s (%d): invalid type given\n",
			       maps[i].name, i);
			return -EINVAL;
		}
	}
	
	maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL);
	maps_node->num_maps = num_maps;
	
	if (dup) {
		maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
					  GFP_KERNEL);
		if (!maps_node->maps) {
			kfree(maps_node);
			return -ENOMEM;
		}
	} else {
		maps_node->maps = maps;
	}
	...
	list_add_tail(&maps_node->node, &pinctrl_maps);
	...
}
pinmux_validate_map()函数

drivers/pinctrl/pinmux.c

int pinmux_validate_map(const struct pinctrl_map *map, int i)
{
	if (!map->data.mux.function) {
		pr_err("failed to register map %s (%d): no function given\n",
		       map->name, i);
		return -EINVAL;
	}

	return 0;
}
pinconf_validate_map()函数

drivers/pinctrl/pinmux.c

int pinconf_validate_map(const struct pinctrl_map *map, int i)
{
	if (!map->data.configs.group_or_pin) {
		pr_err("failed to register map %s (%d): no group/pin given\n",
		       map->name, i);
		return -EINVAL;
	}

	if (!map->data.configs.num_configs ||
			!map->data.configs.configs) {
		pr_err("failed to register map %s (%d): no configs given\n",
		       map->name, i);
		return -EINVAL;
	}

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值