----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4
开发板eMMC
:16GB
LPDDR3
:4GB
显示屏 :15.6
英寸HDMI
接口显示屏u-boot
:2023.04
linux
:6.3
----------------------------------------------------------------------------------------------------------------------------
一、电路原理图
我所使用的NanoPC-T4
开发板可以外接一个散热风扇,我们首先来介绍一下散热风扇硬件相关的内容。
1.1 电路原理图
下图是我们使用的NanoPC-T4
开发板散热风扇的接线图:
VCC_12V0_SYS
为系统电压,电压级别为12V。我们可以通过GPIO
和PWM
实现对风扇的控制;
上图中:
- 当
GPIO4_C6/PWM1
输出高电平时,三极管Q41
导通,N MOS
管Q1
导通,BM03B-GHS-TBT
2号引脚输入12V电鱼,风扇转动; - 当
GPIO4_C6/PWM1
输出低电平时,三极管Q41
截止,N MOS
管Q1
截止,BM03B-GHS-TBT
2号引脚没有电压输入,风扇停止;
至于GPIO2_A6_FAN_TACH
引脚是用来测量转速的。
1.2 散热风扇接口引脚定义
连接器型号: JST GH
系列连接器,3Pin,BM03B-GHS-TBT
:
Pin# | Assignment | Description |
---|---|---|
1 | GND | 0V |
2 | 12V | 12V输出,由GPIO4_C6/PWM1控制 |
3 | GPIO2_A6_FAN_TACH | 用来测量转速 |
二、GPIO
控制
这一节我们将介绍如何通过控制GPIO
口来实现控制散热风扇的运行和停止。
2.1 GPIO
子系统简介
既然是控制GPIO
口,那自然少不了GPIO
子系统。我们在文章《linux
驱动移植-GPIO
子系统》中介绍过GPIO
子系统相关的内容,但是有一块内容却遗漏掉了,那就是有关通过sysfs
来将控制GPIO
。
linux
内核对GPIO
资源进行了抽象,抽象出来的概念就是gpiolib
;gpiolib
汇总了GPIO
的通用操作,根据GPIO
的特性:
- 对上
gpiolib
提供的一套统一通用的操作GPIO
的软件接口,屏蔽了不同芯片的具体实现; - 对下
gpiolib
提供了针对不同芯片操作的一套framework
,针对不同芯片,只需要实现gpio controller driver
,然后使用gpiolib
提供的注册函数,将其挂接到gpiolib
上,这样就完成了这一套东西;
此外,为了方便应用层控制GPIO
口,GPIO
子系统提供了通过sysfs
控制GPIO
就的方式,应用层通过sysfs
操作GPIO
的前提是内核中已经向GPIO
子系统注册GPIO
资源,并且在/sys/class/
目录下可以看到gpio
类。
2.2 内核配置
这里我们需要进行如下配置:
General setup --->
[*] Configure standard kernel features (expert users) // CONFIG_EXPERT
Device Drivers --->
-*- GPIO Support ---> // CONFIG_GPIOLIB
[*] /sys/class/gpio/... (sysfs interface) // CONFIG_GPIO_SYSFS
其中:
CONFIG_GPIO_SYSFS
:决定sysfs
是否支持GPIO
子系统,也就是能否在/sys/class/
目录下看到gpio
类;CONFIG_GPIOLIB
:决定是否将gpiolib
编译进内核,如果选择否则在内核和驱动中不能使用GPIO
子系统相关的函数接口;
CONFIG_GPIOLIB
一般都是选择y
,因为其它驱动会用到GPIO
子系统;CONFIG_GPIO_SYSFS
根据自己的需求来进行选择,如果不需要通过/sys/class/gpio
目录下的文件来操作GPIO
口,就不需要开启。
2.2.1 配置电源域
一般IO
电源的电压有1.8v
,3.3v
,2.5v
,5.0v
等,有些IO
同时支持多种电压,io-domain
就是配置IO
电源域的寄存器,依据真实的硬件电压范围来配置对应的电压寄存器,否则无法正常工作。
在RK3399
的datasheet
中我们搜索GRF_IO_VSEL
寄存器,位于GRF
偏移地址offset
(0x0e640
):
支持两种电压配置:
- 寄存器配置成1,一般对应的电压范围是1.62v ~ 1.98v,
typical
电压 1.8v; - 寄存器配置成0,一般对应的电压范围是3.00v ~ 3.60v,
typical
电压 3.3v。
在 Documentation/devicetree/bindings/power/rockchip-io-domain.yaml文中有关于RK3399 IO
电源域的配置描述描述:
rk3399:
if:
properties:
compatible:
contains:
const: rockchip,rk3399-io-voltage-domain
then:
properties:
audio-supply:
description: The supply connected to APIO5_VDD.
bt656-supply:
description: The supply connected to APIO2_VDD.
gpio1830-supply:
description: The supply connected to APIO4_VDD.
sdmmc-supply:
description: The supply connected to SDMMC0_VDD.
rk3399-pmu:
if:
properties:
compatible:
contains:
const: rockchip,rk3399-pmu-io-voltage-domain
then:
properties:
pmu1830-supply:
description: The supply connected to PMUIO2_VDD.
通过查看rockchip-io-domain.yaml
文中文档, 我们知道了RK3399
的电源域需要配置包含bt565
,audio
,sdmmc
,gpio1830
,以及PMUGRF
下面的pmu1830
这几个supply
,后面的The supplyconnected to ***_VDD
表示在硬件原理图上对应的名称。
我们在rockchip-io-domain.yml
中找到了gpio1830-supply
对应的硬件原理图上表示为APIO4_VDD
。所以通过搜索APIO4_VDD
得到NanoPC-T4
开发板 硬件原理图上的APIO4_VDD
电源VCC_3V0
是由rk808下
的15号引脚VLDO8
输出的;
得到了配置的名称和供电源头,在设备树里面找到对应的regulator: vcc_3v0
,就可以在arch/arm64/boot/dts/rockchip/rk3399-evb.dts
中追加配置;
&io_domains {
bt656-supply = <&vcc_1v8>;
audio-supply = <&vcca1v8_codec>;
sdmmc-supply = <&vcc_sdio>;
gpio1830-supply = <&vcc_3v0>;
status = "okay";
};
&pmu_io_domains {
pmu1830-supply = <&vcc_3v0>;
status = "okay";
};
注意:这里为了方便我直接把所有可能用到的电源域都配置上了。
2.2.2 编译内核
在linux
内核根目录下执行如下命令进行编译内核:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# make -j8
u-boot-2023.04
路径下的mkimage
工具拷贝过来,然后在命令行使用mkimage
工具编译即可:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp ../u-boot-2023.04/tools/mkimage ./
root@zhengyang:/work/sambashare/rk3399/linux-6.3# ./mkimage -f kernel.its kernel.itb
2.2.3 通过tftp
烧录内核
给开发板上电,同时连接上网线,进入uboot
命令行。我们将内核拷贝到tftp
文件目录:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp kernel.itb /work/tftpboot/
接着给开发板上电。通过uboot
命令行将kernel.itb
下到内存地址0x10000000
处:
=> tftp 0x10000000 kernel.itb
通过mmc write
命令将内核镜像烧录到eMMC
第0x8000
个扇区处:
=> mmc erase 0x8000 0xA000
=> mmc write 0x10000000 0x8000 0xA000
2.3 /sys/class/gpio
开发板上电后,查看/sys/class/gpio
目录;
root@rk3399:~# ls /sys/class/gpio
export gpiochip0 gpiochip32 gpiochip96
gpio156 gpiochip128 gpiochip64 unexport
gpiochipXX
:每个文件夹对应一个GPIO
控制器,名字的末尾是GPIO
控制器中第一个GPIO
口在内核中的编号;
每个gpiochipXX
文件夹下面都有base
、label
、ngpio
文件;
root@rk3399:~# ll /sys/class/gpio/gpiochip128
lrwxrwxrwx 1 root root 0 Mar 15 2023 /sys/class/gpio/gpiochip128 -> ../../devices/platform/pinctrl/ff790000.gpio/gpio/gpiochip128/
root@rk3399:~# ls /sys/class/gpio/gpiochip128
base device label ngpio power subsystem uevent
其中:
base
:保存的是GPIO
控制器的第一个GPIO
编号;label
:保存GPIO
控制器标签;ngpio
:GPIO
控制器包含的GPIO
数量;
这些数据是和内核中用来表示GPIO
控制器的struct gpio_chip
结构体对应的,以gpiochip128
为例;
root@rk3399:~# cat /sys/class/gpio/gpiochip128/base
128
root@rk3399:~# cat /sys/class/gpio/gpiochip128/label
gpio4
root@rk3399:~# cat /sys/class/gpio/gpiochip128/ngpio
32
GPIO
控制器名字是gpio4
,包含32
个GPIO
口(GPIO4_A0~A7
、GPIO4_B0~B7
、GPIO4_C0~B7
、GPIO4_D0~D7
),第一个GPIO
口在内核的编号是128,所以该端口包含128-159
号GPIO
口。
2.4 操作GPIO
口
GPIO
资源对上层应用是以文件的形式呈现的