近日OpenWrt官方出了台MT7981的路由器,就是价格非常感人,不过看在它带RTC、POE、GPIO、nor/nand双启动、type-c转串口、还有M2 nvme槽(以及情怀)的份上还是买了一台玩玩。这机器最大的短板就是弱鸡的双核1.3G的MT7981,跑NAT + WiFi到千兆就几乎吃满了CPU(无offload情况),所以想着超个频。
前置知识:MT7981是一个ARMv8-A SoC,一般使用ARM Trusted Firmware(ATF)方式启动,启动顺序为:BL1(BOOT ROM)-> BL2 -> BL31 -> U-boot -> Linux Kernel,BL位于SoC内的ROM,本机从BL2开始位于外置SPI NAND Flash中(通过切换开关进入恢复模式时会使用SPI NOR Flash)。BL2包含了诸多SoC设备初始化代码,其中包含ARMPLL的初始化代码,其为CPU提供高速时钟(PLL初始化前CPU直接使用外部晶振的40MHz时钟)
参考了恩山论坛里的帖子:MT798X CPU超频1.65G/一键修改无线最大功率方法,不过里面的nand固件只有开NMBM(一种NAND Flash坏快管理机制)的,这台机器的主线OpenWrt不使用NMBM,所以用不了。于是自己研究了下,发在这里以供参考,其他没NMBM的nand理论上也能用(但请先确定自己的环境能成功救砖bl2再刷)。
我手里这台能从1.3GHz超到1.7GHz,跑源里的coremark能从4400分提高到5750分。之后再到1.76G时无线高负载时会崩溃重启,到1.8GHz时开机到一半就会死机,大概是这SoC的极限了,求稳可以只超到1.6GHz(此时coremark为5400分)。
方法简而言之就是修改bl2的pll初始化代码,源码位置:arm-trusted-firmware/plat/mediatek/mt7981/drivers/pll/pll.c (mtk-openwrt/arm-trusted-firmware),需要修改其中PLL的频率值和分频值
以下是详细步骤:
- 首先下载最新的OpenWrt 24.10源码,或者直接下载OpenWrt One原厂固件的源码包,里面自带config:https://mirror2.openwrt.org/sources/OpenWrt-One-sources-3098b4bf07.tar.xz
- 先编译一遍代码,确保能成功编译出openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin这个文件,这个就是NAND Flash上的bl2(不要跟nor-preloader搞混,那个是给nor flash的,这机器的nor flash基本只在救砖的时候用),顺便也能把bl2的源码下载下来,供下一步使用
- 编译完后,这里偷个懒,直接编辑openwrt源码目录下的
./build_dir/target-aarch64_cortex-a53_musl/arm-trusted-firmware-mediatek-mt7981-spim-nand-ubi-ddr4/arm-trusted-firmware-mediatek-2024.01.17~bacca82a/plat/mediatek/mt7981/drivers/pll/pll.c
文件(注意这样直接编辑的话make clean后这个文件的改动就丢了,标准做法是写个patch,这里只是图省事),其他机型请根据实际情况修改路径中的spim-nand-ubi-ddr4,找到正确的软件包
需要修改mtk_pll_init()函数其中的/* Set PLL frequency */
这段,具体修改后的代码和解释如下:
/* Set PLL frequency */
// 241208: overclock hack
NOTICE("THIS IS AN OVERCLOKING BL2!\n");
NOTICE("set arm freq to 1.60 GHz:\n");
// 设置频率值,SDMPLL fractional mode,这里只需修改高8位
// 原始为2分频,0x82 = 130,实际对应1.3GHz:
// mmio_write_32(ARMPLL_CON1, 0x82000000); /* 1.3G */)
// 由于这个值再大一些的话会设置失败,所以我们要使用1分频(不分频):
// 例如:0x50 = 80,此时对应1.6G; 0x55 = 85,对应1.7G,一次类推
mmio_write_32(ARMPLL_CON1, 0x50000000); /* 1.6G */
// mmio_write_32(ARMPLL_CON1, 0x55000000); /* 1.7G */
NOTICE("ARMPLL_CON1 = 0x%x\n", mmio_read_32(ARMPLL_CON1));
// 设置分频比,原始为2分频,还有个注释掉的4分频(用这个就是650MHz):
// //mmio_setbits_32(ARMPLL_CON0, 0x124); /* divider for 650M */
// mmio_setbits_32(ARMPLL_CON0, 0x114); /* divider for 1.3G */
// 修改为不分频,这个寄存器的4~6位(从0开始数)为分频值,由于默认是001(2分频),这里要将其清零(1分频),然后再设置其余bits
mmio_clrbits_32(ARMPLL_CON0, 0x70); /* divider for >1.3G */
mmio_setbits_32(ARMPLL_CON0, 0x104);
NOTICE("ARMPLL_CON0 = 0x%x\n", mmio_read_32(ARMPLL_CON0));
- 再次编译(直接make,不要clean),然后刷入
bin/targets/mediatek/filogic/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin到nand
中的bl2分区:- 对于OpenWrt One,可以用nor flash里带的插U盘刷固件方法(请参考该型号OP wiki页面)
- 对于其他设备,请在刷之前一定要保证有救砖手段,例如亲自试试自己电脑用mtk_uartboot能正常工作后再刷
- 还可以在上传到现有系统的/tmp里直接刷:
opkg install mtd kmod-mtd-rw
insmod mtd-rw.ko i_want_a_brick
mtd write /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
mtd verify /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
reboot
下面是我编译的bl2:
对于OpenWrt One,可以直接刷入;
对于其他spim-nand-ubi-ddr4且非NMBM机型,也可以尝试直接刷入;
对于NMBM机型,请使用之前论坛里大佬发的超频bl2,也可以自己参考此方法编译,不要直接刷这个版本;
免责声明:由于刷bl2和超频有不小风险,请在刷之前一定要保证有救砖手段;同时超频会导致功耗增加,会增加供电电路的负荷,会有硬件损坏或者折寿的风险。
参考资料:https://mirror2.openwrt.org/docs/MT7981B_Wi-Fi6_Platform_Registers_Open_Part1_V1.0.pdf ,Page 310~311:
这玩意性价比太低了,更多是社区的意义性质吧,7981 还是双网口,虽然国内的价格倒没有 99 刀…没想到刷到竟然还有人买…
性价比跟那些运营商版的肯定没得比,网口我倒是无所谓,家里都是VLAN交换机,现在也只用插一根线
主要还是选的这SoC不行,这玩意居然是USB3、PCIe和第二个2.5G口三选一,这机器选了PCIe,只剩一个2.5G口要集成交换机芯片也比较蛋疼,如果用MT7531就还是只有一个2.5G
顺便一提着东西似乎买的还不少,淘宝bpi的店里销量300多,现在都没货了