pinctrl虚拟spi的linux驱动,linux内核pinctrl驱动的理解和总结

1. 前言

本站之前的三篇文章[1][2][3]介绍了pin controller(对应的pin controller

subsystem)、gpio controller(对应的GPIO subsystem)有关的基本概念,包括pin

multiplexing、pin configuration等等。本文将基于这些文章,单纯地从pin controller

driver的角度(屏蔽掉pinctrl core的实现细节),理解pinctrl

subsystem的设计思想,并掌握pinctrl驱动的移植和实现方法。

2. pin controller的概念和软件抽象

相信每一个嵌入式从业人员,都知道“pin(管脚)”是什么东西(就不赘述了)。由于SoC系统越来越复杂、集成度越来越高,SoC中pin的数量也越来越多、功能也越来越复杂,这就对如何管理、使用这些pins提出了挑战。因此,用于管理这些pins的硬件模块(pin

controller)就出现了。相应地,linux kernel也出现了对应的驱动(pin controller

driver)。

Kernel pinctrl core使用struct pinctrl_desc抽象一个pin

controller,该结构的定义如下(先贴在这里,后面会围绕这个抽象一步步展开):

struct pinctrl_desc { const char *name; const struct pinctrl_pin_desc *pins; unsigned int npins; const struct pinctrl_ops *pctlops; const struct pinmux_ops *pmxops; const struct pinconf_ops *confops; struct module *owner; #ifdef CONFIG_GENERIC_PINCONF unsigned int num_custom_params; const struct pinconf_generic_params

*custom_params; const struct pin_config_item

*custom_conf_items; #endif };

注1:本文后续的描述基于本站“X Project”所使用的kernel版本[4]。 注2:本文很多的表述(特别是例子),都是引用kernel的document[5](写的很好,可以耐心看看)。

2.1 Pin

kernel的pin

controller子系统要想管理好系统的pin资源,第一个要搞明白的问题就是:系统中到底有多少个pin?用软件语言来表述就是:要把系统中所有的pin描述出来,并建立索引。这由上面struct

pinctrl_desc结构中pins和npins来完成。

对pinctrl

core来说,它只关心系统中有多少个pin,并使用自然数为这些pin编号,后续的操作,都是以这些编号为操作对象。至于编号怎样和具体的pin对应上,完全是pinctrl

driver自己的事情。

因此,pinctrl driver需要根据实际情况,将系统中所有的pin组织成一个struct

pinctrl_pin_desc类型的数组,该类型的定义为:

struct pinctrl_pin_desc { unsigned number; const char *name; void *drv_data; };

number和name完全由driver自己决定,不过要遵循有利于代码编写、有利于理解等原则。另外,为了便于driver的编写,可以在drv_data中保存driver的私有数据结构(可以包含相关的寄存器偏移等信息)。

注3:[5]中有个例子,大家可以参考理解。

2.2 Pin groups

在SoC系统中,有时需要将很多pin组合在一起,以实现特定的功能,例如SPI接口、I2C接口等。因此pin

controller需要以group为单位,访问、控制多个pin,这就是pin groups。相应地,pin controller

subsystem需要提供一些机制,来获取系统中到底有多少groups、每个groups包含哪些pins、等等。

因此,pinctrl core在struct pinctrl_ops中抽象出三个回调函数,用来获取pin

groups相关信息,如下:

struct pinctrl_ops { int (*get_groups_count) (struct pinctrl_dev

*pctldev); const char *(*get_group_name) (struct pinctrl_dev

*pctldev, unsigned selector); int (*get_group_pins) (struct pinctrl_dev

*pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins); void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file

*s, unsigned offset); int (*dt_node_to_map) (struct pinctrl_dev

*pctldev, struct device_node *np_config,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值