概述
在前面两章我们分析了gpio子系统的内容,主要包括gpio子系统内部架构,以及gpio子系统与其他内核子系统的关联等内容,主要主要介绍如何实现一个gpio控制器驱动。
一般来说,gpio控制器驱动一般都是soc厂商实现的,大多数驱动工程师并不需要实现gpio控制器驱动,但我们在开发过程中,当SOC自带的gpio引脚不够时,就可能用到扩展IO芯片来扩展GPIO(一般扩展IO芯片是IIC),当我们使用扩展IO芯片时,还是建议为该扩展IO实现gpio_chip,并注册至gpio子系统中,这样的话访问IO芯片时,可以使用gpio子系统提供的gpio_set_value等接口实现访问,而且还可以很好的和led子系统实现结合,因此作为一个驱动工程师还是建议好好掌握gpio子系统的开发流程,而本章我们则主要从如何实现一个虚拟gpio控制器驱动的角度进行说明。本章的主要内容如下:
一、实现一个gpio控制器驱动流程说明
二、虚拟gpio控制器驱动实现说明
- 虚拟gpio控制器说明
- 虚拟gpio控制器驱动涉及的内容说明
- 虚拟gpio控制器驱动相关的数据结构说明
- 虚拟gpio控制器驱动相关接口实现说明。
一、实现一个gpio控制器驱动流程说明
针对一个gpio控制器驱动,其开发流程主要为如下几步:
- 实现一个struct gpio_chip类型的变量;
- 调用devm_gpiochip_add_data/gpiochip_add完成gpio_chip的注册;
至此,即完成了gpio控制器驱动的注册操作。
二、虚拟gpio控制器驱动实现说明
本小节主要说明如何实现一个虚拟的gpio控制器驱动,从而让我们熟悉gpio控制器驱动的开发流程,让我们在没有开发板的情况下,也可以很好的学习linux gpio子系统驱动。
虚拟gpio控制器说明
虽然是一个虚拟的gpio控制器,但我们还是说明该虚拟gpio控制器的相关参数。针对该虚拟gpio控
制器,主要提供4个寄存器,这四个寄存器的定义如下:
0x00:gpio方向寄存器,用于进行gpio的方向配置,每一位代表一个gpio,1表示输入;0表示输出;
0x08:gpio输入寄存器,用于存储输入方向的gpio的值,该寄存器为只读寄存器;
0x10:gpio输出寄存器,主要用于对配置为输出的gpio值的获取,1表示输出高电平;0表示输出低电平;
0x18:表示中断配置寄存器,主要针对gpio中断使能与关闭,1表示使能中断;0表示关闭中断;
0x20:表示中断状态寄存器,主要用于说明是否产生中断,1表示中断产生;0表示未产生中断,该寄存器只读,且值为读清零。
(本次我们实现的gpio,不涉及gpio中断部分的内容,因中断涉及irq_chip,此处先不实现gpio中断的内容);
虚拟gpio控制器驱动涉及的内容说明
本次驱动开发主要涉及如下两部分的内容:
- 实现一个platform device,用于传递虚拟gpio控制器的信息,包括gpio base index、gpio num等
- 实现一个platform driver,该drvier实现的功能如下:
- platform driver主要用于与上述platform device完成绑定,并根据platform dev提供的控制器参数,填充struct gpio_chip类型变量,并调用gpiochip_add完成gpio_chip的注册;
- 为该platform device在/sys下创建3个属性文件,分别为vgpio_dir(模拟gpio方向寄存器,查看该虚拟gpio控制器的方向配置参数,该属性设置为只读,仅可通过gpio_chip提供的属性文件进行方向配置)、vgpio_in(模拟gpio输入寄存器,该属性为读写,我们可通过修改vgpio_in的值,模拟输入值,用以供虚拟gpio_chip进行查看)、vgpio_out(模拟gpio输出寄存器,该属性为只读)。
虚拟gpio控制器驱动相关的数据结构说明
本次驱动主要涉及两个数据结构:virt_gpio_plat_data_t、virt_gpio_chip_tvirt_gpio_plat_data_t用于platform_device与platform_driver之间传递虚拟gpio控制器的参数,因为我们此次开发的虚拟gpio驱动未使用设备树配置虚拟gpio控制器参数,因此只能借virt_gpio_plat_data_t传递参数,另外当我们使用设备树配置虚拟gpio控制器参数时,可不设gpio base index的值,由系统进行分配;而我们不使用设备树配置虚拟gpio控制器参数时,则建议还是指定gpio base index吧。
virt_gpio_chip_t为本次虚拟gpio控制器相关的私有变量,包括了该虚拟gpio控制器对应的参数,因我们是虚拟gpio控制器,因此我们定义了gpio_dir、gpio_in、gpio_out、gpio_irq模拟四个寄存器,若是真实的gpio控制器,则只需要获取gpio控制器的寄存器地址即可。
如下即为virt_gpio_chip_t与gpio_chips链表以及gpio子系统提供的接口的关联。
虚拟gpio控制器驱动相关接口实现说明
针对虚拟gpio控制器驱动程序,刚才我们已经说明主要涉及platform device、platform driver等下面我们一一说明。
Platform device实现
该platform device主要用于传递虚拟gpio控制器的参数,我们使用platform device、platform driver主要用于实现驱动与设备参数分离,不再驱动中定义涉及设备的参数(关于platform 子系统,可参考我之前写的文章)。
如下即为定义的gpio控制器参数,gpio base index为256,即我们定义的虚拟gpio控制器驱动注册成功后,gpio id范围即为256-319;然后调用platform_device_register注册该platform device即可(若使用设备树,则我们只需在设备树中配置该参数,然后由linux内核解析设备树,并根据该参数创建platform device,相对来说设备树节省了我们自己注册platform device的代码)。
Platform driver实现
在platform driver的probe接口中,主要实现如下几个功能:
- 我们申请virt_gpio_chip_t类型大小的内存空间,并完成成员变量chip的赋值,我们主要设置virt_gpio_dir_set、virt_gpio_direction_input、virt_gpio_direction_output、virt_gpio_get、virt_gpio_set、virt_gpio_request、virt_gpio_free、ngpio、base等参数,接着调用gpiochip_add完成gpio_chip的注册。
- virt_gpio_dir_set、virt_gpio_direction_input、virt_gpio_direction_output、virt_gpio_get、virt_gpio_set这几个函数主要完成gpio方向、gpio输入值获取、gpio输出值设置与获取等参数的设置,主要通过修改virt_gpio_chip_t中的gpio_dir、gpio_in、gpio_out参数实现。
- 为该platform device注册属性文件vgpio_dir、vgpio_in、vgpio_out,这三个文件可以理解为虚拟gpio控制器相关寄存器的外部展现。
实现以上代码功能,即完成了虚拟gpio控制器驱动。
测试验证
当完成驱动的insmod后,即可进行测试,如下所示在/sys/class/gpio下即存在gpiochip256,然后我们export gpio 257,并进入gpio 257,进行gpio的设置,此处我们设置为输入,然后通过向/sys/devices/platform/virt_gpio_dev/vgpio_in中相应位写入0或者1,然后查看gpio 257的value值。至此我们完成了虚拟gpio控制器驱动的验证。
总结
以上即为本章的主要内容,包括如何实现一个gpio 控制器驱动,然后我们实现了一个虚拟的gpio控制器驱动,并完成了验证工作。至此我们完成了gpio 子系统的分析,至于gpio中涉及pinctrl的部分,此次没有介绍,后续会针对pinctrl做单独的分析说明。从下一站开始我们分析led子系统的内容。
本篇文章涉及的代码链接:https://gitee.com/jerry_chg/virt_gpio_controller.git(代码在ubuntu16.04上已完成验证)
最后
以上就是曾经铃铛为你收集整理的Linux gpio 子系统分析之三 虚拟gpio控制器驱动实现一、实现一个gpio控制器驱动流程说明二、虚拟gpio控制器驱动实现说明总结的全部内容,希望文章能够帮你解决Linux gpio 子系统分析之三 虚拟gpio控制器驱动实现一、实现一个gpio控制器驱动流程说明二、虚拟gpio控制器驱动实现说明总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复