pin function和pin group:iomuxc节点解析始末

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

设备树iomuxc节点层次
  • iomuxc

    • function

      • grouc

        fsl,pins = <
        			xxx
        			xxx
        		>;
        

      • group

    • function

层次关系说明
  • iomuxc:pinctrl子系统的设备树节点
  • function:芯片具有外设功能,一个功能对应一个或多个IO组配置信息
  • group:IO组中每个IO的配置信息
  • fsl,pins:imx6ull中,功能和IO组的标识属性
imx_pinctrl_probe_dt()函数

drivers/pinctrl/freescale/pinctrl-imx.c

static int imx_pinctrl_probe_dt(struct platform_device *pdev,
				struct imx_pinctrl *ipctl)
{
	//iomux节点
	struct device_node *np = pdev->dev.of_node;
	struct device_node *child;
	struct pinctrl_dev *pctl = ipctl->pctl;
	//获取iomux节点所对应的device_node指针
    //返回值为true 就是为1
	flat_funcs = imx_pinctrl_dt_is_flat_functions(np);
	if (flat_funcs) {
		nfuncs = 1; //一个芯片外设只使用到了一组引脚 在pinctl子系统里面,至少会有一个function来管理所有的group
	} else {
		nfuncs = of_get_child_count(np);
		if (nfuncs == 0) {
			dev_err(&pdev->dev, "no functions defined\n");
			return -EINVAL;
		}
	}
	//
	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);
        //把这个function_desc的指针插入到pin_function_tree上去
		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)
			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++);
	}

	
imx_pinctrl_dt_is_flat_functions()函数

drivers/pinctrl/freescale/pinctrl-imx.c

static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
{
	struct device_node *function_np;
	struct device_node *pinctrl_np;
	//遍历iomux节点下所有的子节点
	for_each_child_of_node(np, function_np) {
		//判断在子节点里有没有"fsl,pins"属性
		if (of_property_read_bool(function_np, "fsl,pins"))
			return true;
			
		for_each_child_of_node(function_np, pinctrl_np) {
			if (of_property_read_bool(pinctrl_np, "fsl,pins"))
				return false;
		}
	}

	return true;
}
imx_pinctrl_parse_functions()函数

drivers/pinctrl/freescale/pinctrl-imx.c

iomuxc节点的device_node结构体指针, ipctl, 0

参数:imx_pinctrl_parse_functions(np, ipctl, 0);

np–iomux里的device_node结构体指针,ipctl–imx_pinctrl,0

static int imx_pinctrl_parse_functions(struct device_node *np,
				       struct imx_pinctrl *ipctl,
				       u32 index)
{
	struct pinctrl_dev *pctl = ipctl->pctl;
	struct device_node *child;
	struct function_desc *func;
	struct group_desc *grp;
	u32 i = 0;
	//从基数树上把把之前保存的function指针重新提取出来
	func = pinmux_generic_get_function(pctl, index);
	...
    //相当于comptabile
	func->name = np->name;
    //获取iomux节点里的子节点数量(group)
	func->num_group_names = of_get_child_count(np);
	...
	func->group_names = devm_kcalloc(ipctl->dev, func->num_group_names,
					 sizeof(char *), GFP_KERNEL);
	if (!func->group_names)
		return -ENOMEM;

	for_each_child_of_node(np, child) {
        //把子节点的名字记录到group_names数组中
		func->group_names[i] = child->name;

		grp = devm_kzalloc(ipctl->dev, sizeof(struct group_desc),
				   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);

		imx_pinctrl_parse_groups(child, grp, ipctl, i++);
	}

	return 0;
}
pinmux_generic_get_function()函数

drivers/pinctrl/pinmux.c

struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
						  unsigned int selector)
{
	struct function_desc *function;

	function = radix_tree_lookup(&pctldev->pin_function_tree,
				     selector);
	if (!function)
		return NULL;

	return function;
}
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;
	int size, pin_size;
	const __be32 *list, **list_p;
	u32 config;
	int i;
	
	if (info->flags & IMX8_USE_SCU)
		pin_size = FSL_IMX8_PIN_SIZE;
	else if (info->flags & SHARE_MUX_CONF_REG)
		pin_size = FSL_PIN_SHARE_SIZE;
	else
		pin_size = FSL_PIN_SIZE;//24
	
	grp->name = np->name;
	//获取节点属性 二维数组
	list = of_get_property(np, "fsl,pins", &size);
	...
	list_p = &list;
	...
	/*该组引脚的配置个数*/
	grp->num_pins = size / pin_size;
	
	grp->data = devm_kcalloc(ipctl->dev,
				 grp->num_pins, sizeof(struct imx_pin),
				 GFP_KERNEL);
	
	grp->pins = devm_kcalloc(ipctl->dev,
				 grp->num_pins, sizeof(unsigned int),
				 GFP_KERNEL);
	...
    //遍历组里每一个引脚
	for (i = 0; i < grp->num_pins; i++) {
		struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];

		if (info->flags & IMX8_USE_SCU)
			imx_pinctrl_parse_pin_scu(ipctl, &grp->pins[i],
				pin, list_p, config);
		else
			imx_pinctrl_parse_pin_mem(ipctl, &grp->pins[i],
				pin, list_p, config);   //list_p引脚的配置值
	}

	return 0;
}
imx_pinctrl_parse_pin_mem()函数

drivers/pinctrl/freescale/pinctrl-memmap.c

参数:imx_pinctrl_parse_pin_mem(ipctl, &grp->pins[i],pin, list_p, config); //list_p引脚的配置值

int imx_pinctrl_parse_pin_mem(struct imx_pinctrl *ipctl,
			  unsigned int *grp_pin_id, struct imx_pin *pin,
			  const __be32 **list_p, u32 generic_config)
{
	struct imx_pin_memmap *pin_memmap = &pin->pin_conf.pin_memmap;
	const struct imx_pinctrl_soc_info *info = ipctl->info;
    //把二维数组里第一个引脚的配置信息给解析出来 保存到mux_reg上
	u32 mux_reg = be32_to_cpu(*((*list_p)++));
	u32 conf_reg;
	u32 config;
	unsigned int pin_id;
	struct imx_pin_reg *pin_reg;
	
	if (info->flags & SHARE_MUX_CONF_REG) {
		conf_reg = mux_reg;
	} else {
		conf_reg = be32_to_cpu(*((*list_p)++));
		if (!conf_reg)
			conf_reg = -1;
	}
	//获得芯片引脚的编号
	pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
    //找到数组元素
	pin_reg = &ipctl->pin_regs[pin_id];
    //把芯片引脚的编号记录在imx_pin结构体上的int pin
	pin->pin = pin_id;
	*grp_pin_id = pin_id;
	pin_reg->mux_reg = mux_reg;  //复用地址偏移值
	pin_reg->conf_reg = conf_reg; //属性
	pin_memmap->input_reg = be32_to_cpu(*((*list_p)++));
	pin_memmap->mux_mode = be32_to_cpu(*((*list_p)++));
	pin_memmap->input_val = be32_to_cpu((*(*list_p)++));
	...
	config = be32_to_cpu(*((*list_p)++));
	...
	if (config & IMX_PAD_SION)
		pin_memmap->mux_mode |= IOMUXC_CONFIG_SION;
	pin_memmap->config = config & ~IMX_PAD_SION;
	...
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值