Linux内核之pinctrl和gpio子系统

文章详细介绍了IMX6UL平台上Pinctrl子系统的工作原理,包括IOMUXC_SNVS、IOMUXC和gpr控制器的配置,并展示了如何添加PIN信息。同时,文章探讨了GPIO子系统的使用方法,包括设备树中的表示和驱动中的操作函数。此外,还强调了在编写驱动时检查IO冲突和正确配置设备树的重要性。
摘要由CSDN通过智能技术生成

学习链接:https://xuesong.blog.csdn.net/article/details/109522945?spm=1001.2014.3001.5502

一、pinctrl子系统

1.1 IOMUXC SNVS控制器

               iomuxc_snvs: iomuxc-snvs@02290000 {

                compatible = "fsl,imx6ull-iomuxc-snvs";

                reg = <0x02290000 0x10000>;

               };

1.2 IOMUXC控制器

iomuxc: iomuxc@020e0000 {

                     compatible = "fsl,imx6ul-iomuxc";

reg = <0x020e0000 0x4000>;

                     pinctrl-names = "default";

                     pinctrl-0 = <&pinctrl_hog_1>;

                     imx6ul-evk {

                            pinctrl_hog_1: hoggrp-1 {

                                   fsl,pins = <

                                   MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */

                                   MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */

                                   MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */

                                   >;

                            };

                            ………

             

}     

              };

       根据设备的类型,创建对应的子节点,然后设备所用PIN都放到此节点。

1.3 gpr控制器

              gpr: iomuxc-gpr@020e4000 {

                     compatible = "fsl,imx6ul-iomuxc-gpr",

                            "fsl,imx6q-iomuxc-gpr", "syscon";

                     reg = <0x020e4000 0x4000>;

              };

1.4 如何添加一个PIN的信息

              pinctrl_hog_1: hoggrp-1 {

                     fsl,pins = <

                            MX6UL_PAD_UART1_RTS_B__GPIO1_IO19    0x17059 /* SD1 CD */

                     >;

              };

我们在imx6ul-pinfunc.h中找到:

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19         0x0090 0x031C 0x0000 0x5 0x0

<mux_reg     conf_reg input_reg     mux_mode   input_val>

0x0090          0x031C  0x0000          0x5             0x0

IOMUXC父节点首地址0x020e0000,因此UART1_RTS_B这个PIN的mux寄存器地址 就是:0x020e0000+0x0090=0x020e 0090。

conf_reg:0x020e0000+0x031C=0x020e 031C,这个寄存器就是UART1_RTS_B的电气属性配置寄存器。

input_reg,便宜为0,表示UART1_RTS_B这个PIN没有input功能。

mux_mode:5表示复用为GPIO1_IO19,将其写入0x020e 0090

input_val:就是写入input_reg寄存器的值。

0x17059:为PIN的电气属性配置寄存器值。

1.5 pincrtl驱动

       如何找到IMX6UL对应的pinctrl子系统驱动,设备树里面的设备节点是如何根驱动匹配的呢?通过compatible,此属性是字符串列表。驱动文件里面有一个描述驱动兼容性的东西,当设备树节点的compatible属性和驱动里面的兼容性字符串匹配,也就是一模一样的时候就表示设备和驱动匹配了。

       所以我们只需要全局搜索,设备节点里面的compatible属性的值,看看在哪个.c文件里面有,那么此.c文件就是驱动文件。

       找到pinctrl-imx6ul.c文件,那么此文件就是6UL/6ULL的pinctrl驱动文件。

       当驱动和设备匹配以后执行,probe函数。也就是

imx6ul_pinctrl_probe

       ->imx_pinctrl_probe

             

->  此函数会初始化imx_pinctrl_desc,为pinctrl_desc类型的结构体。重点是:

              imx_pinctrl_desc->pctlops = &imx_pctrl_ops;

              imx_pinctrl_desc->pmxops = &imx_pmx_ops;

              imx_pinctrl_desc->confops = &imx_pinconf_ops;

              最后通过pinctrl_register函数向系统注册一个imx_pinctrl_desc

              ->imx_pinctrl_probe_dt

                     ->imx_pinctrl_parse_functions

                            ->imx_pinctrl_parse_groups

                                   ->          pin_reg->mux_reg = mux_reg;

                                          pin_reg->conf_reg = conf_reg;

                                          pin->input_reg = be32_to_cpu(*list++);

                                          pin->mux_mode = be32_to_cpu(*list++);

                                          pin->input_val = be32_to_cpu(*list++);

                                          config = be32_to_cpu(*list++);

                                          if (config & IMX_PAD_SION)

                                          pin->mux_mode |= IOMUXC_CONFIG_SION;

                                          pin->config = config & ~IMX_PAD_SION;

imx_pinconf_set函数设置PIN的电气属性

imx_pmx_set函数设置PIN的复用

二、gpio子系统

2.1 gpio使用方式

1、gpio在设备树中的表示方法

&usdhc1 {

       pinctrl-names = "default", "state_100mhz", "state_200mhz";

       pinctrl-0 = <&pinctrl_usdhc1>;

       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;

       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;

       cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;

       keep-power-in-suspend;

       enable-sdio-wakeup;

       vmmc-supply = <&reg_sd1_vmmc>;

       status = "okay";

};

       定义了一个cd-gpios属性。

       此处使用GPIO1_IO19。  

            gpio1: gpio@0209c000 {

                            compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";

                            reg = <0x0209c000 0x4000>;

                            interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,

                                        <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;

                            gpio-controller;

                            #gpio-cells = <2>;

                            interrupt-controller;

                            #interrupt-cells = <2>;



                     };

devicetree\bindings\gpio

如何从设备树中获取要使用的GPIO信息。of函数。

2、驱动中对gpio的操作函数

1、首先,获取到GPIO所处的设备节点,比如of_find_node_by_path。

2、获取GPIO编号, of_get_named_gpio函数,返回值就是GPIO编号。

3、请求此编号的GPIO,gpio_request函数

4、设置GPIO,输入或输出,gpio_direction_input或gpio_direction_output。

5、如果是输入,那么通过gpio_get_value函数读取GPIO值,如果是输出,通过gpio_set_value设置GPIO值。

2.2 gpio驱动

1、gpiolib

       两部分,给原厂编写GPIO底层驱动的,给驱动开发人员使用GPIO操作函数的。使用gpiochip_add向系统添加gpio_chip,这些都是半导体原厂做的,这部分就是最底层的GPIO驱动。

2、gpio驱动

       在drivers/gpio目录下,gpio-xxx.c文件为具体芯片的驱动文件,

       static struct mxc_gpio_hwdata imx35_gpio_hwdata = {

       .dr_reg           = 0x00,

       .gdir_reg = 0x04,

       .psr_reg  = 0x08,

       .icr1_reg  = 0x0c,

       .icr2_reg  = 0x10,

       .imr_reg  = 0x14,

       .isr_reg   = 0x18,

       .edge_sel_reg = 0x1c,

       .low_level       = 0x00,

       .high_level     = 0x01,

       .rise_edge      = 0x02,

       .fall_edge       = 0x03,

};

mxc_gpio_probe

              -> mxc_gpio_get_hw 获取6ULL的GPIO寄存器组。

              -> bgpio_init 重点初始化gpio_chip

              ->gpiochip_add 向系统添加gpio_chip

三、编写驱动

修改设备树 编写驱动

       申请IO的时候失败,大部分原因是这个IO被其他外设占用了。检查设备树,查找有哪些使用同一IO的设备。

       1,检查复用,也就是pinctl设置。

       2,gpio使用。

四、总结

       1,添加pinctrl信息。

       2,检查当前设备树中要使用的IO有没有被其他设备使用,如果有的话要处理。

       3,添加设备节点,在设备节点中创建一个属性,此属性描述所使用的gpio。

       4,编写驱动,获取对应的gpio编号,并申请IO,成功以后即可使用此IO。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值