㉖AW-H3 Linux驱动开发之clk子系统驱动程序

本次用纯Linux + 自制Filesystem,这种方式更利于学习底层驱动,在说clk子系统之前,我们先说一下如何做最基础的Linux系统,我们这里主要用的是Linux和busybox,其中busybox用来制作文件系统.这一节直接用之前的博客做的文件系统,详细制作步骤参考:

https://blog.csdn.net/qq_23922117/article/details/78312908

下面说一下自己制作Linux系统的详细步骤(参考这里):

①下载Linux内核(Linux-4.11): https://pan.baidu.com/s/1mrac77u5rjdqjgwdVua0CQ 提取码: yub5

②下载之后,先安装tools目录里的dtc工具.解包dtc-master.zip,执行”make && make install”即可;

③新版的uboot需要大于6.x版本以上的编译器才可以,所以配置gcc-linaro-7.2.1交叉编译器,配置步骤参考本文第一个链接;

④我用的板子是SD卡启动(Orange Pi One),我这里把SD卡分了3个区(不含Uboot用的分区):

分区1: 6GB;    // 当正常存储设备使用, fat32格式
分区2: 256MB;  // 存放kernel和dts, ext2格式
分区3: 剩下的容量  // 存放自己做的文件系统, ext2格式

⑤编译uboot:

解包u-boot源码后,进入源码目录:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- orangepi_one_defconfig  //配置uboot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-         //编译

sudo dd if=./spl/sunxi-spl.bin of=/dev/sdb bs=1k seek=8   //烧写bl1到sd卡
sudo dd if=./u-boot.bin of=/dev/sdb bs=1k seek=40         //烧写uboot.bin到sd卡里

⑥编译内核:

解包Linux内核源码之后,进入内核源码目录下操作:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sunxi_defconfig  //配置内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j4   //编译出内核镜像
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs   //编译出设备树文件

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules //编译出驱动模块

把编译出来的zImage, dtb和modules以及之前制作的文件系统放进内存卡,方法如下:

sudo mount /dev/sdb2 mnt/

sudo cp linux-4.11/arch/arm/boot/dts/sun8i-h3-orangepi-one.dtb ./mnt/
sudo cp linux-4.11/arch/arm/boot/zImage ./mnt/

sudo umount mnt/
sudo mount /dev/sdb3 mnt/

cd tools
sudo tar -xvf fs1.tar -C ../mnt/        /* 我这里有一份备份文件系统,解压直接放入sdb3 */
cd ../linux-4.11
sudo make ARCH=arm  modules_install INSTALL_MOD_PATH=../mnt/
sudo umount mnt/

⑦设置uboot启动参数,并完整启动:

首先把内存卡插入开发板,然后开机上电,会在串口终端打印uboot启动信息,按下回车,会出现命令行,输入如下参数:

# 文件系统是ext2的,mmc 0:2是因为内核和dtb在/dev/sdb2
setenv bootcmd "ext2load mmc 0:2 0x46000000 zImage;ext2load mmc 0:2 0x47000000 sun8i-h3-orangepi-one.dtb;bootz 0x46000000 0:0 0x47000000"

# 文件系统在/dev/sdb3,所以是p3,uboot占用blk1,内核就用了blk2,所以是mmcblk2p3
setenv bootargs "root=/dev/mmcblk2p3 rw console=ttyS0,115200n8"

# 保存设置
saveenv

# 重启,区别于boot命令,两者都可以
reset

以上步骤完成之后,就可以正常使用Linux了.

H3器件参数

时钟框架图如下:

datasheet上说有9个PLL部分,分别是:

CPUX, AUDIO, VIDEO, VE, DDR, PERIPH0, GPU, PERIPH1, DE

这些锁相环输出的频率和PLL_N, PLL_K, PLL_M, PLL_P的配置有关.

PLL PLL OUTPUT Range
CPUX PLL_CPUX = (24MHz * N * K) / (M * P) 200MHz~2.6GHz
AUDIO

PLL_AUDIO = (24MHz * N) / (M * P)

PLL_AUDIO(8X) = (24MHz * N * 2) / M

PLL_AUDIO(4X) = PLL_AUDIO(8X) / 2

PLL_AUDIO(2X) = PLL_AUDIO(4X) / 2

20MHz~200MHz
VIDEO

Integer mode:

PLL_VIDEO = (24MHz * N) / M

Fractional mode:

BIT(25) = 0-->output = PLL_VIDEO

BIT(25) = 1-->output = PLL_VIDEO * 2

30MHz~600MHz
VE

Integer mode:

PLL_VE = (24MHz * N) / M

Fractional mode:

PLL_VE output is select by bit 25

30MHz~600MHz
DDR PLL_DDR = (24MHz * N * K) / M 200MHz~2.6GHz
PERIPH0 PLL_PERIPH0 = (24MHz * N * K) / 2 200MHz~1.8GHz
GPU

Integer mode:

PLL_GPU = (24MHz * N) / M

Fractional mode:

PLL_GPU output is select by bit 25

30MHz~600MHz
PERIPH1 PLL_PERIPH1 = (24MHz * N * K) / 2 200MHz~1.8GHz
DE

Integer mode:

PLL_DE = (24MHz * N) / M

Fractional mode:

PLL_DE output is select by bit 25

default:297MHz

上面表格的范围值只是说这些锁相环具备在这个范围的输出能力,并不代表实际上可以输出这么多,比如CPU,PLL_CPUX的输出能力范围是200MHz~2.6GHz,实际当中,让H3运行在1.5GHz都比较困难,另外,通过实践证明,CPU可以运行在60MHz,可能是真正运行在60MHz,也可能只是软件设置了60MHz,而实际硬件并没有降到这么低的频率,官方提供的数据只是作为一种参考.

Linux时钟子系统

H3上的代码结构

实际代码

实际代码量比较大,单个文件不能代表整个子系统,这里就不贴出代码了,可以下载代码之后进行查看.

https://pan.baidu.com/s/1mrac77u5rjdqjgwdVua0CQ 提取码: yub5

效果验证

从H3的datasheet上可以看到:

Clock output of PLL_CPUX is used only for CPUX, and the frequency factor can be dynamically modified for DVFS;
Clock output of PLL_AUDIO can be used for I2S/PCM, AC DIGITAL, OWA etc, and dynamic frequency scaling is not supported;
Clock output of PLL_PERIPH0 can be used for MBUS/AHB1/AHB2/APB1/APB2 and NAND/MMC/Crypto Engine/SPI/CSI/DE/DEINTERLACE etc, and dynamic frequency scaling is not supported;
Clock output of PLL_PERIPH1 can be used for NAND/MMC/SPI/CSI/TVE/DEINTERLACE etc, and dynamic frequency scaling is not suppoerted;
Clock output of PLL_VE can be used for VE, and dynamic frequency scaling is not supported;
Clock output of PLL_DDR can be used for MBUS and DRAM, and dynamic frequency scaling is not supported;
Clock output of PLL_VIDEO0 can be used for DE, TCON, HDMI, and CSI, and dynamic frequency scaling is not supported;
Clock output of PLL_DE can be used for DE, TCON and TVE, and dynamic frequency scaling is not supported;
Clock output of PLL_HSIC can be used for CCI-400 and USBPHY, and dynamic frequency scaling is not supported;
Clock output of PLL_GPU can be used for GPU, and dynamic frequency scaling is not supported;

可以看出,只有CPU支持动态调节时钟频率,其它的都是静态调节,那么,我们还是以CPU进行验证,验证方法就是之前博客里写的cpufreq,先来看一下dts的CPU部分:

&cpu0 {
	operating-points = <
		1008000	1300000
		816000	1100000
		624000	1100000
		480000	1100000
		312000	1100000
		240000	1100000
		120000	1100000
		>;
	#cooling-cells = <2>;
	cooling-min-level = <0>;
	cooling-max-level = <6>;
	cpu0-supply = <&vdd_cpux>;
};

在dts里只描述了CPU0,其它几个CPU没有描述,原因是此CPU并没有采用异构技术,只能同频运行,也就是在H3这个CPU上,任何一个CPU的频率都和其它3个CPU的频率一样,任何一个CPU频率发生改变,其它3个CPU也会跟着改变,采用异构的CPU在这里不讨论,另外从dts上可以看到,其采用的是频率电压对应的方式进行频率的调节,因为ARM SoC一般不具备独立调整频率的能力,往往SoC的CPUfreq驱动需要一个频率表,频率在该表的范围之内进行变更.dts上的这个频率表太保守,H3还可以发挥出更好的性能,我们让它"超频"(相对于这个dts的超频),做如下修改:

...
		regulator-max-microvolt = <1400000>;
		...
		states = <1100000 0x0
			  1400000 0x1>;
...

&cpu0 {
	operating-points = <
		1368000	1400000
		1200000	1320000
		816000	1100000
		624000	1100000
		240000	1100000
		120000	1100000
		60000	1100000
		>;
	#cooling-cells = <2>;
	cooling-min-level = <0>;
	cooling-max-level = <6>;
	cpu0-supply = <&vdd_cpux>;
};

把最大频率改到了1368MHz,最低频率改到了60MHz,性能与续航结合,因为在大多数时间手机都处于待机状态,虽然,待机时有,CPUfreq, CPUidle, devfreq和Android的PowerManager等进行参与,但这里只考虑cpufreq,运行在60MHz则会相对来说更节能一些,在真正用户在使用时,上升到1368MHz比之前的1008MHz效果好很多,验证情况如下图:

猜你喜欢

转载自blog.csdn.net/qq_23922117/article/details/86625288