《原子Linux驱动开发》+pinctrl和gpio子系统
[复制链接]
先了解一下什么是pinctrl和gpio子系统。
pinctrl子系统和gpio子系统在Linux驱动开发中扮演着重要的角色。
pinctrl子系统主要用于引脚的配置,包括复用为不同的引脚模式(如GPIO模式、I2C模式等)以及配置引脚的电气特性。在硬件属性方面,pinctrl子系统的相关信息放在设备树(dts)中。它涉及到两个主要对象:pin controller和client device。Pin controller提供服务,如复用引脚和配置引脚,而client device则声明自己要使用的引脚及其功能。
gpio子系统则用于初始化GPIO,并提供相应的API函数,如设置GPIO为输入输出、读取GPIO的值等。当pinctrl子系统将某个PIN复用为GPIO模式后,gpio子系统就可以用来控制这个引脚了。gpio子系统的主要目的是方便驱动开发者使用gpio,他们可以在设备树中添加gpio相关信息,然后在驱动程序中使用gpio子系统提供的API函数来操作GPIO。
下面对PIN 配置信息详解:
在Linux内核的设备树(Device Tree)中,iomuxc节点通常用于描述引脚复用控制器(Pin Multiplexer Controller)的配置信息,它允许你将硬件引脚(PIN)配置为不同的功能(如GPIO、UART、I2C等)。这些信息对于pinctrl子系统来说是至关重要的,因为它需要知道如何配置这些引脚以满足硬件驱动的要求。
在imx6ull.dtsi文件中,你可以找到类似iomuxc的节点,它包含了多个子节点,每个子节点描述了一组引脚(PIN group)的配置。每个PIN group通常包含一组具有相同或相似功能的引脚,并且这些引脚可以一起被配置为特定的模式。
如何根据iomuxc节点中的compatible属性值来找到对应的Linux内核驱动文件。在您的例子中,compatible属性的值为"fsl,imx6ul-iomuxc",这通常意味着内核中应该有一个与之匹配的驱动文件。
通过全局搜索字符串"fsl,imx6ul-iomuxc",您已经找到了对应的驱动文件drivers/pinctrl/freescale/pinctrl-imx6ul.c。这个文件是Freescale(现在是NXP)i.MX6UL系列处理器的pinctrl驱动实现。
在这个驱动文件中,您会看到如何解析设备树中的配置信息,并设置相应的引脚复用和配置。这通常涉及到以下几个关键步骤:
- 驱动注册:驱动会注册自己到pinctrl子系统,以便其他驱动可以使用它。
- 解析设备树:驱动会解析设备树中的iomuxc节点及其子节点,以获取引脚配置信息。
- 配置引脚:根据解析得到的配置信息,驱动会设置硬件的引脚复用和电气特性。
- 提供引脚组:驱动会创建并导出引脚组(PIN groups),这些引脚组可以被其他驱动使用。
如果您正在为i.MX6UL平台编写或调试驱动,并需要配置特定的引脚,那么您需要确保:
- 设备树中的iomuxc节点及其子节点正确描述了您的引脚配置需求。
- pinctrl-imx6ul.c驱动文件(或任何后续更新的版本)正确解析并应用了这些配置。
- 您的驱动或应用程序正确地请求并使用了由pinctrl子系统提供的引脚组。
gpio子系统API函数:
gpio_request()函数、gpio free()函数、 gpio_direction input()函数、gpio direction output()函数、gpio_get_value()函数、gpio_set_value()函数。
对于驱动开发人员来说,设置好设备树后,使用GPIO子系统提供的API函数来操作指定的GPIO可以大大简化开发过程。这种驱动分层与分离的设计有助于确保每个组件都专注于其特定的职责,从而提高了整体的可维护性和可扩展性。
GPIO子系统提供了一些常用的API函数,这些函数允许驱动开发人员以更高级、更抽象的方式来操作GPIO,而无需关心底层的寄存器读写细节。以下是一些常用的GPIO子系统API函数:
- gpio_request函数:
- 功能:用于申请一个GPIO管脚。在使用一个GPIO之前,必须使用此函数进行申请。
- 函数原型:int gpio_request(unsigned gpio, const char *label)
- 参数:
- gpio:要申请的GPIO标号,通常使用of_get_named_gpio函数从设备树中获取。
- label:GPIO的标签(别名),用于标识该GPIO。
- 返回值:成功返回0,失败返回其他值。
- gpio_free函数:
- 功能:释放之前申请的GPIO资源。
- 函数原型:void gpio_free(unsigned gpio)
- 参数:gpio:要释放的GPIO标号。
- gpio_direction_input函数:
- 功能:设置GPIO为输入模式。
- 函数原型:int gpio_direction_input(unsigned gpio)
- 参数:gpio:要设置为输入模式的GPIO标号。
- 返回值:成功返回0,失败返回负值。
- gpio_direction_output函数:
- 功能:设置GPIO为输出模式。
- 函数原型:int gpio_direction_output(unsigned gpio, int value)
- 参数:
- gpio:要设置为输出模式的GPIO标号。
- value:初始输出值(0或1)。
- 返回值:成功返回0,失败返回负值。
- gpio_get_value函数:
- 功能:获取指定GPIO的当前值(0或1)。
- 函数原型:int gpio_get_value(unsigned gpio)
- 参数:gpio:要获取值的GPIO标号。
- 返回值:GPIO的当前值(0或1)。
- gpio_set_value函数:
- 功能:设置指定GPIO的输出值。
- 函数原型:void gpio_set_value(unsigned gpio, int value)
- 参数:
- gpio:要设置值的GPIO标号。
- value:要设置的输出值(0或1)。
在Linux设备树(Device Tree)中创建设备节点并添加pinctrl和gpio属性信息,是配置和控制硬件资源(如LED灯)的重要步骤。以下是一个逐步的过程,说明如何在设备树中创建test节点,并添加pinctrl和gpio信息。
1. 创建 test 设备节点
首先,在设备树的根节点/下创建test设备子节点。这个节点将包含描述test设备的信息。
2. 添加 pinctrl 信息
接下来,向test节点添加pinctrl信息。这通常包括pinctrl-names属性,用于描述pinctrl状态的名字,以及pinctrl-x属性,用于引用pinctrl状态的节点。
假设您已经在设备树中创建了名为pinctrl_test的pinctrl状态节点,并且这个节点描述了test设备所使用的GPIO引脚配置。现在,将这个节点引用添加到test设备节点中。
3. 添加 GPIO 属性信息
最后,向test节点添加GPIO属性信息。这通常包括gpios属性,用于指定test设备所使用的GPIO引脚以及相关的配置信息(如激活电平)。
在驱动开发中,您可以使用Linux内核提供的pinctrl 和gpio 子系统API来访问和控制这些资源。可以使用pinctrl_get() 函数获取pinctrl状态句柄,使用gpio_request() 函数请求GPIO引脚,以及使用gpio_direction_output() 函数设置GPIO为输出等。这些API函数将抽象底层的硬件细节,使驱动开发更加便捷和可移植。
|