pinctrl设备驱动(1)

一、pinctrl注册函数
 

int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|                               struct device *dev,
|                               void *driver_data,
|                               struct pinctrl_dev **pctldev
|-->static struct pinctrl_dev * pinctrl_init_controller(
    |                           struct pinctrl_desc *pctldesc,
    |                           struct device *dev,
    |                           void *driver_data
    |-->static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
                                const struct pinctrl_pin_desc *pins,         //pin描述符数组
                                unsigned int num_descs)                        //pin描述符数组长度,即pin数量

二、pinctrl使能函数

在驱动初始化探测过程调用注册函数pinctrl_register_and_init之后,还需要直接调用使能函数pinctrl_enable。

static LIST_HEAD(pinctrldev_list); //pin控制器设备全局链表

int pinctrl_enable(struct pinctrl_dev *pctldev)
|
|--> static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
     |
     |-->static struct pinctrl *create_pinctrl(struct device *dev,
                                                struct pinctrl_dev *pctldev)
     |                          
     |-->struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, 
                                                const char *name)
     |
     |-->int pinctrl_select_state(struct pinctrl *p,  struct pinctrl_state *state)
     |     |->pinctrl_commit_state
     |-->pinctrl_lookup_state()
|
|--> list_add_tail(&pctldev->node, &pinctrldev_list); //将本设备插入全局链表

  • pinctrl_lookup_state根据名称查询pinctrl结构是否存在要查找的状态,状态有“default”、“init”、“idle”、“sleep”四种,这四种描述了控制器的硬件状态。
  • pinctrl_select_state将硬件设置到一种新的pinctrl状态,硬件状态由pinctrl结构保存。从老状态退出需要调用pinmux_disable_setting,新状态才能使能生效通过调用pinmux_enable_setting和pinconf_apply_setting,最后再修改pinctrl结构的状态信息。

三、核心数据结构

2.1 pinctrl_desc描述符
struct pinctrl_desc {
	const char *name;                   //pinctrl驱动名称
	const struct pinctrl_pin_desc *pins;//pin描述符数组
	unsigned int npins;                 //pin描述符数组长度,即pin数量
	const struct pinctrl_ops *pctlops;  //pinctrl操作向量表,用于支持pin分组等全局操作
	const struct pinmux_ops *pmxops;    //pinmux操作向量表,如果本驱动支持pin复用操作
	const struct pinconf_ops *confops;  //pinconf操作向量表,如果本驱动支持pin配置操作
	struct module *owner;               //指向pinctrl驱动所属的内核模块
	bool link_consumers;                //所有请求pinctrl驱动服务的消费者链表
};
2.2 pinctrl_pin_desc描述符
struct pinctrl_pin_desc {
	unsigned int number;  //pin编号,即pinctrl驱动范围内的唯一编号
	const char *name;     //pin名称
	void *drv_data;       //pinctrl驱动指针
};
#define PINCTRL_PIN(a, b) { .number = a, .name = b }

pinctrl的设备驱动程序一般用PINCTRL_PIN宏来静态定义所有pin描述符数组:

​
static const struct pinctrl_pin_desc tegra_dpaux_pins[] = 
{ 
    PINCTRL_PIN(0, "DP_AUX_CHx_P"), 
    PINCTRL_PIN(1, "DP_AUX_CHx_N"), 
};

​

2.3 pingroup描述符

struct pingroup {
	const char *name;                //pingroup名称
	const unsigned int *pins;        //分组内的pin编号数组
	size_t npins;                    //数组长度
};
#define PINCTRL_PINGROUP(_name, _pins, _npins)	\
(struct pingroup) {				\
	.name = _name,				\
	.pins = _pins,				\
	.npins = _npins,			\
}

pinctrl的设备驱动程序一般用PINCTRL_PINGROUP宏来静态定义所有pin分组:

static const unsigned int cs42l43_pin_gpio1_pins[] = { 0 };
static const unsigned int cs42l43_pin_gpio2_pins[] = { 1 };
static const unsigned int cs42l43_pin_gpio3_pins[] = { 2 };
static const unsigned int cs42l43_pin_asp_pins[] = { 3, 4, 5 };
static const unsigned int cs42l43_pin_pdmout2_pins[] = { 6, 7 };
static const unsigned int cs42l43_pin_pdmout1_pins[] = { 8, 9 };
static const unsigned int cs42l43_pin_i2c_pins[] = { 10, 11 };
static const unsigned int cs42l43_pin_spi_pins[] = { 12, 13, 14 };

#define CS42L43_PINGROUP(_name) \
	PINCTRL_PINGROUP(#_name, cs42l43_pin_##_name##_pins, \
			 ARRAY_SIZE(cs42l43_pin_##_name##_pins))

static const struct pingroup cs42l43_pin_groups[] = {
	CS42L43_PINGROUP(gpio1),
	CS42L43_PINGROUP(gpio2),
	CS42L43_PINGROUP(gpio3),
	CS42L43_PINGROUP(asp),
	CS42L43_PINGROUP(pdmout2),
	CS42L43_PINGROUP(pdmout1),
	CS42L43_PINGROUP(i2c),
	CS42L43_PINGROUP(spi),
};

四、操作

3.1 分组操作
  • get_groups_count:获取全局的分组数量;
  • get_group_name: 获取指定分组的组名称;
  • get_group_pins: 获取指定分组的pin编码数组和数组长度;
  • dt_node_to_map: 分配设备树“pin configuration node”,并创建相应的映射表,返回pinctrl_map表项数组和数组长度,如果pinctrl设备驱动不支持设备树,该操作为NULL;
  • dt_free_map: 释放映射表;也就是说允许pinctrl驱动根据设备树动态映射和释放映射表。

注意:Linux内核称分组操作为全局性操作,主要原因是:pinctrl有两个基本功能,复用和配置。

3.2 复用操作

        复用是指,芯片pin信号可以连接内部多个功能部件,在一个时刻,pin只能由其中的一个功能部件使用。

  • request:pinctrl框架层调用该方式判断给定的pin是否可以复用;如果不满足复用条件,返回一个负的错误码。对于一个指定pin,request操作一旦成功相当于申请到该pin的复用权限;
  • free:在pinctrl框架层调用request操作成功之后,pinctrl框架层才能调用free操作释放指定的pin;
  • get_function_count:返回pinctrl驱动管理的复用功能的数量;
  • get_function_name:返回指定编号的复用功能名称;
  • get_function_group:返回指定编号的复用功能对应的分组名称,这样再通过全局/分组操作来获取相应的pin。注意,该操作可能返回多个分组名称。
  • set_mux:在指定pin分组上将指定的复用功能使能。该函数不需要考虑指定pin分组其他复用功能的冲突问题;因为冲突有pinctrl/pinmux框架处理。
  • gpio_request_enable:在指令pin上请求和使能GPIO功能。当pinctrl所管理的每一个pin都可以独立成为GPIO时,可以实现该函数。gpio相关的操作的pin集合,是以pinctrl_gpio_range描述符来定义的,这个概念与前面介绍的复用功能和pin分组是两个维度。pinctrl框架层来处理以保证不发生冲突。
  • gpio_disable_free: gpio_request_enable的反向操作。
  • gpio_set_direction: 设置方向。

3.3 配置操作

该配置操作是设置和查询pin或pin分组的方向特性、开/漏等电气特性。

  •         pin_config_get/set
  •         pin_config_group_get/sisi
  • 28
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值