第7阶段:完善WiFi-蓝牙

目标

让 WCN3620 这颗 WiFi/蓝牙 SoC 跑起来——dmesg 里看到 wlan0hci0 注册成功。

硬件分析

Y927 用的 WiFi/蓝牙是 Qualcomm WCN3620——MSM8916 板上的协处理器,跟主 SoC 共享 SMD 总线,整条链路涉及 6 个角色

角色 内核模块 DTS 节点 作用
协处理器加载 qcom_wcnss_pil (CONFIG_QCOM_WCNSS_PIL) &wcnss 用 PIL 把 wcnss.mdt 加载到协处理器
协处理器内存 &wcnss_mem 给 WCNSS 预留 6 MiB 共享内存
RF 子模块 &wcnss_iris 声明 RF 子模块型号(qcom,wcn3620
WiFi MAC wcn36xx (CONFIG_WCN36XX) 通过 SMD 自动关联 注册 wlan0
蓝牙 HCI btqcomsmd (CONFIG_BT_QCOMSMD) 通过 SMD 自动关联 注册 hci0
WCNSS 控制通道 qcom_wcnss_ctrl (CONFIG_QCOM_WCNSS_CTRL) SMD 通道里的 RPC 控制面

WCN3620 是仅 2.4 GHz 的单频版本——通过 compatible = "qcom,wcn3620" 区分(如果是 5 GHz 兼容的 WCN3680,driver 走另一套校准路径)。

DTS 改动分析

板级只需要 3 段(全部 override 父 dtsi 里的默认 disabled):

1
2
3
4
5
6
7
8
9
10
11
12
13

/* ====== WiFi / 蓝牙 (WCNSS 协处理器 + WCN3620 RF) ====== */
&wcnss {
status = "okay";
};

&wcnss_iris {
compatible = "qcom,wcn3620"; /* Y927 实测;与 lk2nd DTS 一致 */
};

&wcnss_mem {
status = "okay";
};

ℹ️ 不需要写 GPIO/pinctrl/regulatormsm8916.dtsi 已经把 WCNSS 的 IRIS regulator (pm8916_l7 / pm8916_s3 / pm8916_s4)、SMP2P、SMSM、IRQ 全部连好,板级只补"启用"+"型号确认"两件事。

ℹ️ WCN3620 vs WCN3680 怎么判:lk2nd DTS、原厂 msm8x16-pinctrl.dtsi 或拆机看主板字符。Y927 是 WCN3620(仅 2.4 GHz,不支持 5 GHz)。

内核配置

1
2
3
4
5
6
7
8
9
10
cd ~/y927/linux
./scripts/config --enable QCOM_WCNSS_PIL
./scripts/config --enable QCOM_WCNSS_CTRL
./scripts/config --enable WCN36XX
./scripts/config --enable BT
./scripts/config --enable BT_QCOMSMD
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig

busybox grep -E '^CONFIG_(WCN36XX|QCOM_WCNSS|BT_QCOMSMD|BT)=' .config
# 期望全部 =y

编译 Linux 内核

1
2
cd ~/y927/linux
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image.gz dtbs

提取WiFi固件

WCNSS 涉及两类文件,路径必须平铺在 /lib/firmware/ 根下(在纯 initramfs 阶段,没有 pmOS deviceinfo 的 firmware-search-path 注入):

文件 路径(纯 initramfs 阶段) 来源 大小
wcnss.mdt /lib/firmware/ 原厂 NON-HLOS.bin 解出 ~7 KB
wcnss.b00/b01/b02/b04/b06/b09/b10/b11 同上 同上 共 ~600 KB
WCNSS_qcom_wlan_nv.bin /lib/firmware/wlan/prima/ 原厂 persist 分区 ~3 KB(逐机不同
WCNSS_qcom_cfg.ini /lib/firmware/wlan/prima/ 原厂 system.img ~50 KB(可选)

最终 initramfs /lib/firmware/ 目录树:

1
2
3
4
5
6
7
8
9
/lib/firmware/
├── a300_pfp.fw ← GPU 固件
├── a300_pm4.fw ← GPU 固件
├── wcnss.mdt ← WCNSS PIL 镜像
├── wcnss.b00 ~ wcnss.b11 ← WCNSS PIL 镜像
└── wlan/
└── prima/
├── WCNSS_qcom_wlan_nv.bin ← WiFi RF 校准(每机不同)
└── WCNSS_qcom_cfg.ini ← WiFi 配置(可选)

提取 wcnss.mdt + b00…b11 文件

1
2
3
4
5
6
7
rm -rf ~/y927/wcnss-extracted && mkdir -p ~/y927/wcnss-extracted
rm -rf /tmp/nonhlos && mkdir -p /tmp/nonhlos
sudo mount -o loop,ro \
"/home/zzq/y927/Y927(PD1410V)升级软件_an/NON-HLOS.bin" \
/tmp/nonhlos
cp /tmp/nonhlos/image/wcnss.* ~/y927/wcnss-extracted/
sudo umount /tmp/nonhlos

提取 WCNSS_qcom_cfg.ini 文件和 WCNSS_qcom_wlan_nv.bin 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

uv tool install 'git+https://github.com/zhangzqs/qfil-unsparse-py'
qfil-unsparse --help
sudo apt install -y android-sdk-libsparse-utils

cd ~/y927/Y927\(PD1410V)升级软件_an/
qfil-unsparse -x rawprogram_unsparse.xml -p system -o /tmp
qfil-unsparse -x rawprogram_unsparse.xml -p persist -o /tmp

sudo debugfs -R "dump /etc/wifi/WCNSS_qcom_cfg.ini \
/home/zzq/y927/wcnss-extracted/WCNSS_qcom_cfg.ini" \
/tmp/system.img

sudo debugfs -R "dump /WCNSS_qcom_wlan_nv.bin \
/home/zzq/y927/wcnss-extracted/WCNSS_qcom_wlan_nv.bin" \
/tmp/persist.img

制作initramfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
BUSYBOX_BINARY=~/y927/busybox-1.38.0/busybox
EVTEST_BINARY=~/y927/evtest/src/evtest
PHASE_ID=7
cd ~/y927/initramfs
rm -rf phase-$PHASE_ID
mkdir -p phase-$PHASE_ID && cd phase-$PHASE_ID
INITRAMFS=~/y927/initramfs/phase-$PHASE_ID
FIRMWARE_GPU=~/y927/firmware-gpu
WCNSS_EXTRACTED=~/y927/wcnss-extracted

# 创建 initramfs 目录结构
mkdir -p bin dev proc sys \
lib/modules \
lib/firmware/qcom \
lib/firmware/wlan/prima

# 复制 BusyBox 到 initramfs
cp $BUSYBOX_BINARY bin/
cp $EVTEST_BINARY bin/

# GPU 微码固件
cp $FIRMWARE_GPU/a300_pm4.fw $INITRAMFS/lib/firmware/qcom/
cp $FIRMWARE_GPU/a300_pfp.fw $INITRAMFS/lib/firmware/qcom/

# WiFi/蓝牙 固件
cp $WCNSS_EXTRACTED/wcnss.* $INITRAMFS/lib/firmware/
cp $WCNSS_EXTRACTED/WCNSS_qcom_cfg.ini $INITRAMFS/lib/firmware/wlan/prima/
cp $WCNSS_EXTRACTED/WCNSS_qcom_wlan_nv.bin $INITRAMFS/lib/firmware/wlan/prima/

# 创建基础命令的软链接
cd bin
for cmd in sh mount ls cat sleep exec echo; do
ln -sf busybox $cmd
done
cd ..

# 创建 /init 脚本
cat > init << 'EOF'
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t devtmpfs dev /dev
echo "===== Phase 1: kernel booted! ====="
echo "Serial: $(cat /proc/cmdline)"
sleep 5
exec sh </dev/ttyGS0 >/dev/ttyGS0 2>&1
EOF
chmod +x init

# 打包
find . | cpio -o -H newc | gzip > ../initramfs-phase-$PHASE_ID.cpio.gz

构建 boot.img 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd ~/y927/linux
PHASE_ID=7

# 拼接内核 + DTB
cat arch/arm64/boot/Image.gz \
arch/arm64/boot/dts/qcom/msm8916-vivo-y927.dtb \
> vmlinuz-dtb

~/y927/lk2nd/lk2nd/scripts/mkbootimg \
--kernel vmlinuz-dtb \
--ramdisk $HOME/y927/initramfs/initramfs-phase-$PHASE_ID.cpio.gz \
--cmdline "console=tty0 console=ttyMSM0,115200 panic=1 initcall_blacklist=simpledrm_platform_driver_init" \
--base 0x80000000 \
--kernel_offset 0x00008000 \
--ramdisk_offset 0x01000000 \
--second_offset 0x00f00000 \
--tags_offset 0x00000100 \
--pagesize 2048 \
--header_version 0 \
--output boot-phase-$PHASE_ID.img

刷入 boot.img 文件

1
2
3
PHASE_ID=7
fastboot flash boot boot-phase-$PHASE_ID.img
fastboot reboot

测试

1
sudo picocom -b 115200 /dev/ttyACM0

2026-06-14 23:00 WiFi/蓝牙全部识别。

1. dmesg 关键行(WCNSS 完整链路)

1
2
3
4
5
6
7
[    0.379]  remoteproc remoteproc0: Booting fw image wcnss.mdt, size 7260          ← PIL 加载固件
[ 0.936] remoteproc remoteproc0: remote processor a204000.remoteproc is now up ← 协处理器起来
[ 1.038] qcom_wcnss_ctrl ...: WCNSS Version 1.5 1.2 ← SMD 通道 ready
[ 1.057] wcn36xx: mac address: 02:00:06:9a:cc:1b ← wcn36xx 拿到 MAC
[ 1.06 ] wcn36xx: firmware WLAN version 'WCN v2.0 RadioPhy vIris_TSMC_4.0 ...' ← RF 固件版本
[ 1.07 ] wcn36xx: firmware API 1.5.1.2, 41 stations, 2 bssids ← 容量(41 个 AP + 2 个 BSSID)
[ 1.10 ] Bluetooth: hci0: ... ← 蓝牙 HCI 注册

2. WiFi 接口注册

1
2
3
4
5
6
~ # busybox ls /sys/class/net/
lo wlan0
~ # busybox ip link set wlan0 up
~ # busybox ip link show wlan0
2: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
link/ether 02:00:06:9a:cc:1b brd ff:ff:ff:ff:ff:ff

02:00:06:9a:cc:1b 是从 Y927 自己的 persist 分区 NV 校准里读出来的,每台机器不同
<NO-CARRIER,...UP> 状态正常——initramfs 阶段不接 AP,没 carrier 正常。

注:initramfs 阶段没有 iw/wpa_supplicant,无法扫 AP 或连 WPA;需要真 rootfs 阶段才能完整联网测试。

3. 蓝牙 HCI 注册

1
2
3
4
~ # busybox ls /sys/class/bluetooth/
hci0
~ # busybox cat /sys/class/bluetooth/hci0/address
02:00:06:9a:cc:1a ← 蓝牙 MAC