1、内核提供了 pinctrl 和 gpio 子系统用于 gpio驱动。linux是一个庞大而又完善的系统 不可能 让你用裸板开发的方式 去 操作 gpio.
该系统是按照面向对象的设计思想设计的。
pinctrl
子系统主要工作内容如下:
①、获取设备树中 pin 信息。
②、根据获取到的 pin 信息来设置 pin 的复用功能
③、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。
对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始
化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目录为 drivers/pinctrl
。
要使用
pinctrl
子系统,我们需要在设备树里面设置
PIN
的配置信息,毕竟
pinctrl
子系统要
根据你提供的信息来配置
PIN
功能,一般会在设备树里面创建一个节点来描述
PIN
的配置信
息,这部分代码是由半导体厂商 软件工程师 写了这部分代码 由kernel 进行加载的。
gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO
为输入输出,读取 GPIO 的值等。
Linux
内核向驱动开发者屏蔽掉了
GPIO
的
设置过程
,极大的方便了驱动开发者使用
GPIO
。
,设置好设备树以后就可以使用
gpio 子系统提供 的 API 函数
来操作指定 的
GPIO
,
gpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程
。这就是
驱动分层
与
分离
的好处,大家各司其职,做好自己的本职工作即可。
iomuxc
节点的
imx6ul-evk
子节点下创建一个名为“
pinctrl_led
”的子节点
pinctrl_led
:
ledgrp
{
fsl
,
pins
= <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03
0x10B0
/* LED0 */
>;
}
;
添加
LED
设备节点
在根节点“
/
”下创建
LED
灯节点,节点名为“
gpioled
”,
gpioled
{
#address
-
cells
= <
1
>;
#size
-
cells
= <
1
>;
compatible
=
"atkalpha-gpioled"
;
pinctrl
-
names
=
"default"
;
pinctrl
-
0
= <&
pinctrl_led
>;
led
-
gpio
= <&
gpio1
3
GPIO_ACTIVE_LOW
>;
status
=
"okay"
;
}
;
检查
PIN
有没有被其他外设使用包括两个方
面:
①
、检查 pinctrl 设置。
②、
如果这个 PIN 配置为 GPIO 的话,检查这个 GPIO 有没有被别的外设使用
480
pinctrl_tsc
:
tscgrp
{
481
fsl
,
pins
= <
482
MX6UL_PAD_GPIO1_IO01__GPIO1_IO01
0xb0
483
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02
0xb0
484
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03
0xb0
485
MX6UL_PAD_GPIO1_IO04__GPIO1_IO04
0xb0
486
>;
487
};
检查
GPIO_IO03
这个
PIN
有没
有被其他的
pinctrl
节点使用
和
C
语言一样,在要
屏蔽的内容前后加上“
/*
”和“
*/
”符号即可。
在
imx6ull-alientek-emmc.dts
中搜索 “
gpio1 3
”
723
&
tsc
{
724
pinctrl
-
names
=
"default"
;
725
pinctrl
-
0
= <&
pinctrl_tsc
>;
726
xnur
-
gpio
= <&
gpio1
3
GPIO_ACTIVE_LOW
>;
727
measure
-
delay
-
time
= <
0xffff
>;
728
pre
-
charge
-
time
= <
0xfff
>;
729
status
=
"okay"
;
730
};
tsc
外设也使用了
GPIO1_IO03
,同样我们需
要将这一行屏蔽掉。然后在继续搜索“
gpio1 3
”,看看除了本章的
LED
灯以外还有没有其他的
地方也使用了
GPIO1_IO03
,找到一个屏蔽一个。
如果 cat /sys/firmware/devicetree/base 可以看到节点信息 gpioled 子节点
那么 设备树修改成功。