pinctrl子系统(五):引脚状态设置与查询

pinctrl子系统的引脚设置接口

pinctrl子系统对外接口
状态查询接口

pinctrl_lookup_state

状态设置接口

pinctrl_select_state

状态类型
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_INIT "init"
#define PINCTRL_STATE_IDLE "idle"
#define PINCTRL_STATE_SLEEP "sleep"
函数原型
pinctrl_lookup_state()函数

drivers/pinctrl/core.c

struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
						 const char *name)//这个name就是defualt之类的
{
	struct pinctrl_state *state;
	//找到与name相等的state
	state = find_state(p, name);
	
	if (!state) {
		if (pinctrl_dummy_state) {
			/* create dummy state */
			dev_dbg(p->dev, "using pinctrl dummy state (%s)\n",
				name);
			state = create_state(p, name);
		} else
			state = ERR_PTR(-ENODEV);
	}

	return state;
}
find_state()函数

drivers/pinctrl/core.c

static struct pinctrl_state *find_state(struct pinctrl *p,const char *name)
{
	struct pinctrl_state *state;

	list_for_each_entry(state, &p->states, node)
	//在遍历p->states链表头,看state->name是否与要查找的相等
		if (!strcmp(state->name, name))
			return state;

	return NULL;
}
pinctrl_select_state()函数//真正设定引脚状态

drivers/pinctrl/core.c

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()函数

drivers/pinctrl/core.c

static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
{
	struct pinctrl_setting *setting, *setting2;
	struct pinctrl_state *old_state = p->state;
	int ret;
	
	...
	
	list_for_each_entry(setting, &state->settings, node) {//遍历pinctrl——state结构体的setting链表节点
		switch (setting->type) {//根据type进行不同的配置
		case PIN_MAP_TYPE_MUX_GROUP://设置复用属性
			ret = pinmux_enable_setting(setting);
			break;
		case PIN_MAP_TYPE_CONFIGS_PIN://设置io具体属性
		case PIN_MAP_TYPE_CONFIGS_GROUP:
			ret = pinconf_apply_setting(setting);
			break;
		default:
			ret = -EINVAL;
			break;
		}
	
	
pinmux_enable_setting()函数
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;
	
	int ret = 0;
	const unsigned *pins = NULL;
	unsigned num_pins = 0;
	int i;
	struct pin_desc *desc;
	
	if (pctlops->get_group_pins)
	 //pinctrl_generic_get_group_pins(),从中得到pin name和num
		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,&pins, &num_pins);

	...
	//imx_pmx_set函数
	ret = ops->set_mux(pctldev, setting->data.mux.func,
			   setting->data.mux.group);
	...
}
pinctrl_generic_get_group_pins()函数

drivers/pinctrl/pinmux.c

int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev,
				   unsigned int selector,
				   const unsigned int **pins,
				   unsigned int *num_pins)
{
	struct group_desc *group;
	
	//在group_desc基数树当中找到对应group的group_desc
	group = radix_tree_lookup(&pctldev->pin_group_tree,
				  selector);
	if (!group) {
		dev_err(pctldev->dev, "%s could not find pingroup%i\n",
			__func__, selector);
		return -EINVAL;
	}

	*pins = group->pins;
	*num_pins = group->num_pins;

	return 0;
}
imx_pmx_set()函数

drivers/pinctrl/freescale/pinctrl-imx.c

static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,unsigned group)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	unsigned int npins;
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	int i, err;
	struct group_desc *grp = NULL;
	struct function_desc *func = NULL;

	/*
	 * Configure the mux mode for each pin in the group for a specific
	 * function.
	 */
	grp = pinctrl_generic_get_group(pctldev, group);//找到group_desc指针
	if (!grp)
		return -EINVAL;

	func = pinmux_generic_get_function(pctldev, selector);//找到function_desc指针
	if (!func)
		return -EINVAL;

	npins = grp->num_pins;//引脚组要配置的引脚个数

	dev_dbg(ipctl->dev, "enable function %s group %s\n",
		func->name, grp->name);

	for (i = 0; i < npins; i++) {//对每一个需要配置的引脚进行配置
		struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];//获取imx——pin
		if (info->flags & IMX8_USE_SCU)
			err = imx_pmx_set_one_pin_scu(ipctl, pin);
		else
			err = imx_pmx_set_one_pin_mem(ipctl, pin);//
		if (err)
			return err;
	}

	return 0;
}
imx_pmx_set_one_pin_mem()函数

drivers/pinctrl/freescale/pinctrl-memmap.c

int imx_pmx_set_one_pin_mem(struct imx_pinctrl *ipctl, struct imx_pin *pin)
{
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	unsigned int pin_id = pin->pin;//引脚编号
	struct imx_pin_reg *pin_reg;
	struct imx_pin_memmap *pin_memmap;
	pin_reg = &ipctl->pin_regs[pin_id];//找到相应寄存器地址
	pin_memmap = &pin->pin_conf.pin_memmap;//记录了芯片 引脚的具体配置值
	//知道了寄存器地址和具体的配置值,就可以对寄存器进行配置了
	if (info->flags & SHARE_MUX_CONF_REG) {
		u32 reg;
		reg = readl(ipctl->base + pin_reg->mux_reg);
		reg &= ~info->mux_mask;
		reg |= (pin_memmap->mux_mode << info->mux_shift);
		writel(reg, ipctl->base + pin_reg->mux_reg);
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
			pin_reg->mux_reg, reg);
	} else {
		writel(pin_memmap->mux_mode, ipctl->base + pin_reg->mux_reg);//将mux_mode写入寄存器
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
			pin_reg->mux_reg, pin_memmap->mux_mode);
	}
	...
 }
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值