----------------------------------------------------------------------------------------------------------------------------开发板 久久派开发板eMMC8GBDDR4512MBu-bootu-boot 2022.04linux6.12rootfsbuildroot-2024.08----------------------------------------------------------------------------------------------------------------------------我们使用的是久久派开发板WiFi版本开发板使用的WiFi芯片为CDW.20800D4这是AIC(爱科微) 生产的一款集成了WiFi和蓝牙二合一通信模组。我们之前移植了linux 6.12版本的内核这个版本的内核默认并没有支持CDW.20800D4因此我们需要去移植相应的驱动。在《Rockchip RK3399 - WiFi AP6356驱动》我们对WiFi概念进行了大量的介绍本篇博客不再赘述。一、CDW.20800D420800D4系列是一款单芯片无线局域网(WLAN)和蓝牙(BT)组合解决方案支持1 × 1 IEEE 802.11a/b/g/n/ac/ax WLAN标准以及BT 5.4能够实现WLAN/BT与低功耗技术的无缝集成。特性说明接口支持低功耗 SDIO 3.0 接口(用于 WLAN)以及 UART/PCM 接口(用于 BT)集成度提供高度集成的 WLAN 系统级芯片(SoC)适用于 5GHz 802.11ac 或 2.4GHz/5GHz 802.11n WLAN 应用频段支持支持 WLAN 2.4GHz 和 5GHz 频段信道蓝牙支持支持 BT 5.4、BLE、ANT并向后兼容 BT 1.x 和 BT 2.x EDR(增强数据速率)射频设计支持单端射频端口可实现更简洁、更低成本的设计信道带宽2.4GHz 支持 20MHz/40MHz5GHz 支持 20MHz、40MHz先进技术支持 MU-MIMO(多用户多输入多输出)和 OFDMA(正交频分多址)更多有关CDW.20800D4的内容参考《久久派无线模块规格书/5_CDW.20800D4_Series_specification_V1.3_20240201.pdf》。1.1 功能框图CDW.20800D4功能框图如图所示现在很多模组都是是集成了WiFi和蓝牙功能的所以我们不只看到有WiFi使用的SDIO接口还有用于蓝牙通讯的UART、PCM接口。我们播放歌曲的时候音乐的数据的传输使用的是UART接口如果是蓝牙通话的时候使用的是PCM接口。所以我们可以在WiFi和蓝牙二合一的芯片上看到3种接口其中SDIO是WiFi的UART和PCM是蓝牙的。1.1.1Wi-Fi (SDIO)引脚引脚名称说明14SD_DAT2SDIO DATA215SD_DAT3SDIO DATA316SD_CMDSDIO 命令线17SD_CLKSDIO 时钟18SD_DAT0SDIO DATA019SD_DAT1SDIO DATA11.1.2 蓝牙 (UART) 引脚引脚名称说明41UART_RTS蓝牙 UART RTS42UART_TX蓝牙 UART TX43UART_RX蓝牙 UART RX44UART_CTS蓝牙 UART CTS1.1.3 控制引脚引脚名称说明12WL_DISWi-Fi 使能 (L关闭, H开启)6Host wake BT主机唤醒蓝牙7BT wake host蓝牙唤醒主机13WL_Wake-up hostWi-Fi 唤醒主机1.1.4 电源要求电压最小值典型值最大值VDD (3.3V)3.0V3.3V3.6VVDDIO1.7/3.0V1.8/3.3V1.9/3.6V1.2 电路原理图下图是我们使用的是久久派开发板CDW.20800D4的电路原理图从原理图可以看到CDW.20800D4使用的通信接口是SDIO接口。此外与WiFi相关比较重要的引脚WLAN_EN用于WiFi部分的使能连接龙芯处理器TIM1_CH1引脚(即GPIO81)。二、CDW.20800D4设备驱动SDIO总线和USB总线类似SDIO也有两端其中一端为主机(Host)端另一端是设备端(Device)采用Host-Device这样的设计是为了简化Device的设计所有的通信都由Host端发出命令开始、在Device端只要能解析Host发出的命令就可以同Host进行通信了SDIO的Host可以连接多个Device。SDIO的驱动可以分为SDIO主机控制器驱动针对不同主机端的SDIO控制器的驱动主机端SDIO设备驱动针对不同客户端的设备驱动程序。如SD卡、T-Flash卡、SDIO接口的GPS和WiFi等设备驱动而WiFi设备驱动实际上又涉及到多个驱动模块比如rfkill驱动802.11模块驱动、以及WiFI设备自身驱动。2.1SDIO主机控制器驱动2.1.1sdio1节点配置由于WiFi通信使用SDIO接口因此需要配置相应的设备树。这里我们使用的是sdio1sdio节点定义在arch/loongarch/boot/dts/loongson-2k0300.dtsisdio1: sdio0x16148000 { #address-cells 2; compatible loongson,ls2k_sdio_1.2; reg 0 0x16148000 0 0x8000; interrupt-parent liointc1; interrupts 0 IRQ_TYPE_LEVEL_HIGH; // 32 - 32 0 interrupt-names ls2k_mci_irq; dma-mask 0xffffffff 0xffffffff; clock-frequency 0 200000000; pinctrl-0 sdio1_pins; pinctrl-names default; cap-sd-highspeed; cap-mmc-highspeed; bus-width 4; status disabled; }; pinmux: pinmux16000490 { ...... sdio1_pins: pinmux_G100_G105_as_sdio { pinctrl-single,bits 0x18 0x000fff00 0x000fff00; }; }sdio1引脚复用信息如下sdio1_pins用于将GPIO100到GPIO105这6个引脚配置为SDIO功能。我们需要修改arch/loongarch/boot/dts/ls2k300_99pi_wifi.dts文件sdio1 { /delete-property/ cd-gpios; status okay; cs-gpios gpio 81 GPIO_ACTIVE_HIGH; };这里借用cs-gpios属性传入GPIO81用于控制模组的WLAN_EN引脚将其拉高后WiFi模组上电/使能。它不是标准SDIO协议里的片选信号。2.1.2 源码调整修改drivers/mmc/host/ls2kmci.c中ls2k_mci_probe函数...... #include linux/of_gpio.h ...... static int ls2k_mci_probe(struct platform_device *pdev) { hotpug_host host; local_irq_save(flags); if (request_irq(host-irq, ls2k_mci_irq, 0, DRIVER_NAME, host)) { dev_err(pdev-dev, failed to request mci interrupt.\n); ret -ENOENT; goto probe_iounmap; } ...... // 以下为手动添加 host-cs_gpio of_get_named_gpio(pdev-dev.of_node, cs-gpios, 0); if (gpio_is_valid(host-cs_gpio)) { gpio_direction_output(host-cs_gpio, 1); printk(successfully %s: Toggled CS GPIO 1 for %s\n, __func__, mmc_hostname(mmc)); } else { printk(Error %s: Cannot get CS GPIO for %s\n, __func__, mmc_hostname(mmc)); } // 以上为手动添加 ...... } static noinline void ls2k_mci_send_command(struct ls2k_mci_host *host, struct mmc_command *cmd) { u32 ccon; if (cmd-data) { host-complete_what COMPLETION_XFERFINISH_RSPFIN; } else if (cmd-flags MMC_RSP_PRESENT) host-complete_what COMPLETION_RSPFIN; else host-complete_what COMPLETION_CMDSENT; writel(cmd-arg, host-base SDICMDARG); ccon cmd-opcode SDICMDCON_INDEX; ccon | SDICMDCON_SENDERHOST | SDICMDCON_CMDSTART; /* Emmc cmd6 do not need data transfer */ if (host-pdata-version LOONGSON_SDIO_EMMC_VER_1_0 cmd-opcode SD_SWITCH cmd-data) ccon | SDICMDCON_CMD6DATA; if (cmd-flags MMC_RSP_PRESENT) ccon | SDICMDCON_WAITRSP; if (cmd-flags MMC_RSP_136) ccon | SDICMDCON_LONGRSP; // 以下为手动添加 unsigned int val; if (cmd-opcode 53){ val readl(host-base SDIDCON); val | (0x3 24); writel(val, host-base SDIDCON); } // 以上为手动添加 writel(ccon, host-base SDICMDCON); }修改drivers/mmc/host/ls2kmci.h中struct ls2k_mci_host结构体struct ls2k_mci_host { int cs_gpio; //手动添加 ..... }注意必须要修改源码不然内核加载会出现如下错误[ 28.854568] aicbsp: sdio_err:aicwf_sdio_bus_txmsg,1120: send faild:1, 0,0 [ 31.862567] cmd timed-out [ 31.865232] tkn[0] flags:0012 result: -4 cmd:1024 - reqcfm(1025) [ 48.509697] audit: type1334 audit(1721825419.905:9): prog-id10 opUNLOAD2.2WiFi设备驱动WiFI设备自身驱动一般都是由WiFi芯片厂家提供比如WiFi芯片厂商瑞昱、博通这部分是标准的基本不用修改不管是NXP、Rockchip、全志、龙芯等平台都是使用这一套代码。2.2.1 源码AIC8800的驱动源码可以从多个渠道获取包括芯片厂商提供的官方版本、社区维护的版本以及各大设备厂商定制化的版本。这里我们使用久久派定制化的版本这个版本适配的是linux 4.19版本的内核因此需要进行调整这个代码我做了linux 6.12版本的适配源码位于《https://gitee.com/zyly2033/loongson_2k300_lib/tree/master/driver/wifi》zhengyangubuntu:/opt/2k0300/loongson_2k300_lib/driver/wifi$ ls -l drwxrwxrwx 5 zhengyang zhengyang 4096 5月 8 17:10 aic8800 drwxrwxr-x 2 zhengyang zhengyang 4096 5月 8 16:42 firmware其中aic8800目录下存放的就是驱动源码firmware目录下存放着安装驱动时依赖的固件。当然如果有兴趣可以尝试从gitHub获取社区维护的驱动源码这个版本编译错误比较多改动比较多git clone https://github.com/goecho/aic8800_linux_drvier.git2.2.2 编译首次编译尝试zhengyangubuntu:/opt/2k0300/loongson_2k300_lib/driver/$ cd wifi/aic8800 zhengyangubuntu:/opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800$ make clean zhengyangubuntu:/opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800$ make ...... LD [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_fdrv/aic8800_fdrv.o MODPOST /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/Module.symvers CC [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_btlpm/aic8800_btlpm.mod.o LD [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_btlpm/aic8800_btlpm.ko CC [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_fdrv/aic8800_fdrv.mod.o LD [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_fdrv/aic8800_fdrv.ko CC [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_bsp/aic8800_bsp.mod.o LD [M] /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_bsp/aic8800_bsp.ko make[1]: 离开目录“/opt/2k0300/build-2k0300/workspace/linux-6.12”成功后会生成三个.ko文件aic8800_bsp/aic8800_bsp.ko这是底层BSP/总线支撑模块主要负责AIC8800芯片的底层通信、SDIO/USB传输接口、固件下载、芯片初始化、寄存器访问、电源/复位等基础能力通常WLAN主驱动会依赖它aic8800_fdrv/aic8800_fdrv.ko 这是WiFi功能主驱动负责注册无线网卡、对接Linux cfg80211/nl80211、创建wlan0这类网络接口处理扫描、连接、AP模式、收发包、加密、信道切换、雷达检测等WiFi功能也就是真正用来跑WiFi的核心模块aic8800_btlpm/aic8800_btlpm.ko这是蓝牙低功耗/休眠管理模块BT LPM大概率是Bluetooth Low Power Mode。主要负责蓝牙侧的休眠唤醒、GPIO wake、hostwake/btwake、/proc/bluetooth/sleep相关控制等。拷贝到install目录cp /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/modules.order /opt/2k0300/loongson_2k300_lib/driver/wifi/install cp /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_btlpm/aic8800_btlpm.ko /opt/2k0300/loongson_2k300_lib/driver/wifi/install cp /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_fdrv/aic8800_fdrv.ko /opt/2k0300/loongson_2k300_lib/driver/wifi/install cp /opt/2k0300/loongson_2k300_lib/driver/wifi/aic8800/aic8800_bsp/aic8800_bsp.ko /opt/2k0300/loongson_2k300_lib/driver/wifi/installmodules.order记录模块构建/安装顺序。2.3 其它驱动模块配置进入内核配置界面zhengyangubuntu:~$ cd /opt/2k0300/build-2k0300/workspace/linux-6.12 zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh make menuconfig2.3.1IEEE 802.11驱动需要配置内核支持IEEE 802.11驱动[*] Networking support --- -*- Wireless --- M cfg80211 - wireless configuration API默认会生成配置CONFIG_CFG80211m实际上arch/loongarch/configs/loongson_2k300_defconfig文件已经配置了。2.3.2rfkill驱动需要配置内核支持rfkill驱动rfkill是Linux内核提供的RF开关框架用于统一管理WiFi、蓝牙等无线设备的启用/禁用状态。具体的上电、复位、唤醒GPIO仍然需要由平台设备树、板级代码或具体驱动完成。内核配置如下[*] Networking support --- [M] RF switch subsystem support --- [*] RF switch input support默认会生成配置CONFIG_RFKILLm CONFIG_RFKILL_INPUTy实际上arch/loongarch/configs/loongson_2k300_defconfig文件已经配置了。2.3.3 编译内核ubuntu宿主机重新编译内核zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh make uImage -j$(nproc)2.3.4 拷贝驱动我们将驱动拷贝到/opt/2k0300/loongson_2k300_lib/driver/wifi/install目录zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ cp /opt/2k0300/build-2k0300/workspace/linux-6.12/net/wireless/cfg80211.ko /opt/2k0300/loongson_2k300_lib/driver/wifi/install zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ cp /opt/2k0300/build-2k0300/workspace/linux-6.12/net/rfkill/rfkill.ko /opt/2k0300/loongson_2k300_lib/driver/wifi/install三、测试3.1 烧录设备树3.1.1 编译设备树如果需要单独编译设备树在linux内核根目录执行如下命令zhengyangubuntu:~$ cd /opt/2k0300/build-2k0300/workspace/linux-6.12 zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh make dtbs V13.1.2 更新设备树将设备树拷贝到久久派的/opt目录zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ scp arch/loongarch/boot/dts/ls2k300_99pi_wifi.dtb root172.23.17.235:/opt在久久派使用dd命令烧写设备树到SPI Nor Flash的dtb分区[rootLS-GD opt]# dd if/opt/ls2k300_99pi_wifi.dtb of/dev/mtdblock3 bs1 221240 records in 221240 records out 22124 bytes (22 kB, 22 KiB) copied, 0.500342 s, 44.2 kB/s [rootLS-GD opt]# reboot3.2 烧录内核由于我们在前面的环节修改了SDIO主机控制器驱动源码因此需要重新编译烧录内核。3.2.1 编译内核ubuntu宿主机重新编译内核zhengyangubuntu:/opt/2k0300/build-2k0300/workspace/linux-6.12$ source ../set_env.sh make uImage -j$(nproc)3.2.2 烧录内核久久派烧录内核即将编译生成的uImage(内核镜像)拷贝到/boot目录[rootLS-GD ~]# scp zhengyang172.23.16.99:/opt/2k0300/build-2k0300/workspace/linux-6.12/arch/loongarch/boot/uImage /boot/ [rootLS-GD ~]# reboot3.3 安装WiFi设备驱动将我们整个WiFi模块从宿主机拷贝到久久派zhengyangubuntu:/opt/2k0300/loongson_2k300_lib/driver/wifi$ scp -r /opt/2k0300/loongson_2k300_lib/driver/wifi root172.23.17.235:/opt久久派执行[rootLS-GD opt]# ls -l wifi/ total 6 -rw-r--r-- 1 root root 2527 Jul 25 04:08 README.md drwxr-xr-x 5 root root 1024 Jul 25 04:08 aic8800 drwxr-xr-x 2 root root 1024 Jul 25 04:08 firmware drwxr-xr-x 2 root root 1024 Jul 25 04:08 install3.3.1 启动加载如果希望系统启动自动加载该驱动我们需要将驱动拷贝到/usr/lib/modules/6.12.0.lsgd/内核启动的时候使用/sbin/modprobe加载/lib/modules/{uname -r}下面的模块modules.order只记录模块构建/安装顺序真正决定modprobe自动加载依赖的是depmod生成的modules.dep。[rootLS-GD ~]# cd /usr/lib/modules/$(uname -r)/ [rootLS-GD 6.12.0.lsgd]# cp /opt/wifi/install/* /usr/lib/modules/6.12.0.lsgd [rootLS-GD 6.12.0.lsgd]# ls -l -rw-r--r-- 1 root root 186872 Jul 24 21:20 aic8800_bsp.ko -rw-r--r-- 1 root root 12704 Jul 24 21:20 aic8800_btlpm.ko -rw-r--r-- 1 root root 890872 Jul 24 21:20 aic8800_fdrv.ko -rw-r--r-- 1 root root 831752 Jul 24 21:20 cfg80211.ko -rw-r--r-- 1 root root 23312 Jul 24 2024 encoder.ko -rw-r--r-- 1 root root 237 Jul 24 21:20 modules.order -rw-r--r-- 1 root root 63880 Jul 24 21:20 rfkill.ko需要在加载模块之前建立该模块的依赖关系也即必须用depmod来更新一下/lib/modules/$(uname -r)/modules.dep文件[rootLS-GD 6.12.0.lsgd]# depmod -a此时生成modules.depencoder.ko: rfkill.ko: cfg80211.ko: rfkill.ko aic8800_bsp.ko: aic8800_btlpm.ko: aic8800_bsp.ko rfkill.ko aic8800_fdrv.ko: cfg80211.ko aic8800_bsp.ko rfkill.ko3.3.2 拷贝固件我们需要在久久派开发板创建目录[rootLS-GD 6.12.0.lsgd]# mkdir -p /lib/firmware/aic8800_fw/SDIO/aic8800D80路径必须正确如需将固件放在其它路径需要修改驱动源码。把这些文件放进去[rootLS-GD 6.12.0.lsgd]# cp -r /opt/wifi/firmware/* /lib/firmware/aic8800_fw/SDIO/aic8800D80 [rootLS-GD ~]# ls -l /lib/firmware/aic8800_fw/SDIO/aic8800D80 -rw-r--r-- 1 root root 2683 Jul 24 20:54 aic_userconfig_8800d80.txt -rw-r--r-- 1 root root 331348 Jul 24 20:54 fmacfw_8800d80_u02.bin -rw-r--r-- 1 root root 333388 Jul 24 20:54 fmacfwbt_8800d80_u02.bin -rw-r--r-- 1 root root 1708 Jul 24 20:54 fw_adid_8800d80_u02.bin -rw-r--r-- 1 root root 30040 Jul 24 20:54 fw_patch_8800d80_u02.bin -rw-r--r-- 1 root root 1048 Jul 24 20:54 fw_patch_table_8800d80_u02.bin -rw-r--r-- 1 root root 237206 Jul 24 20:54 lmacfw_rf_8800d80_u02.bin3.4 加载验证3.4.1 内核启动日志[rootLS-GD ~]# dmesg | grep -Ei mmc|sdio|aic|wifi [ 0.000000] DMI: Loongson LS2K300/LS2K300-99PI-WIFI, BIOS 2022.04-g96038f5a-dirty 04/01/2022 [ 0.000000] Kernel command line: earlycon fbconlogo-pos:center fbconlogo-count:1 consolettyS0,115200 rw noinitrd init/sbin/init rootfstypeext4 rootwait root/dev/mmcblk0p1 mtdpartsspi0.0:924k(uboot),32k(uboot_env),4k(bdinfo),52k(dtb),4k(bdinfo_e),8k(ddr_context) fbconrotate:0 paneldefault bp_start0x900000000f030400 board_nameLS2K300-99PI-WIFI [ 0.000000] Unknown kernel command line parameters paneldefault board_nameLS2K300-99PI-WIFI, will be passed to user space. [ 1.272151] ls2k_sdio 16140000.sdio: Use exclusive dma engine. [ 1.279687] Error ls2k_mci_probe: Cannot get CS GPIO for mmc0 [ 1.713771] ls2k_sdio 16148000.sdio: Use exclusive dma engine. [ 1.727677] successfully ls2k_mci_probe: Toggled CS GPIO 1 for mmc1 [ 6.373952] mmc1: new high speed SDIO card at address 42f1 [ 6.773970] Waiting for root device /dev/mmcblk0p1... [ 7.036200] mmc0: new high speed MMC card at address 0001 [ 7.042381] mmcblk0: mmc0:0001 08A391 7.28 GiB [ 7.049301] mmcblk0: p1 [ 7.053721] mmcblk0boot0: mmc0:0001 08A391 4.00 MiB [ 7.060118] mmcblk0boot1: mmc0:0001 08A391 4.00 MiB [ 7.154435] EXT4-fs (mmcblk0p1): mounted filesystem 77fabf5f-333f-4f1b-9c30-f01c7422efda r/w with ordered data mode. Quota mode: none. [ 7.194114] board_nameLS2K300-99PI-WIFI [ 9.836662] EXT4-fs (mmcblk0p1): re-mounted 77fabf5f-333f-4f1b-9c30-f01c7422efda r/w. Quota mode: none. [ 18.506079] aic8800_bsp: loading out-of-tree module taints kernel. [ 18.710695] aicbsp_init [ 18.860602] aicbsp_resv_mem_init [ 22.844244] aicbsp: aicbsp_set_subsys, subsys: AIC_WIFI, state to: 1 [ 22.917591] aicbsp: aicbsp_set_subsys, power state change to 1 dure to AIC_WIFI [ 22.994589] aicbsp: aicbsp_platform_power_on [ 23.187483] aicbsp: aicbsp_sdio_probe:1 vid:0xC8A1 did:0x0082 [ 23.244053] aicbsp: aicbsp_sdio_probe:2 vid:0xC8A1 did:0x0182 [ 23.305583] aicbsp: aicbsp_sdio_probe after replace:1 [ 23.361598] AICWFDBG(LOGINFO) aicwf_sdio_chipmatch USE AIC8800D80 [ 23.424610] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 23.493585] aicbsp: aicwf_sdio_reg_init [ 23.548832] AICWFDBG(LOGINFO) aicbsp: aicbsp_driver_fw_init, chip rev: 7 [ 23.617611] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_patch_table_8800d80_u02.bin [ 23.864887] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_adid_8800d80_u02.bin [ 24.091587] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_patch_8800d80_u02.bin [ 24.657893] aicbt_patch_table_load bt btmode[3]:5 [ 24.671091] aicbt_patch_table_load bt uart_baud[3]:1500000 [ 24.679417] aicbt_patch_table_load bt uart_flowctrl[3]:1 [ 24.686002] aicbt_patch_table_load bt lpm_enable[3]:0 [ 24.692140] aicbt_patch_table_load bt tx_pwr[3]:28463 [ 24.755738] aicbsp: bt patch version: - Mar 07 2024 14:29:05 - git f94a3e4 [ 24.785752] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fmacfw_8800d80_u02.bin [ 25.279926] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 25.286544] aicsdio: aicwf_sdio_reg_init [ 25.296102] aicbsp: aicbsp_resv_mem_alloc_skb, alloc resv_mem_txdata succuss, id: 0, size: 98304 [ 25.305423] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 25.311997] aicbsp: sdio_err:aicwf_sdio_bus_pwrctl,1384: bus down [ 25.319135] AICWFDBG(LOGINFO) aicwf_prealloc_txq_alloc size is diff will to be kzalloc [ 25.327539] AICWFDBG(LOGINFO) aicwf_prealloc_txq_alloc txq kzalloc successful [ 25.356965] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_42 [ 25.362897] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_58 [ 25.368850] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_106 [ 25.377066] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_122 [ 25.383235] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_138 [ 25.389337] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_155 [rootLS-GD ~]# dmesg ...... [ 13.050727] cfg80211: Loading compiled-in X.509 certificates for regulatory database [ 13.284832] Loaded X.509 cert sforshee: 00b28ddf47aef9cea7 [ 13.308749] Loaded X.509 cert wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600 [ 18.506079] aic8800_bsp: loading out-of-tree module taints kernel. [ 18.710695] aicbsp_init [ 18.860602] aicbsp_resv_mem_init [ 22.844244] aicbsp: aicbsp_set_subsys, subsys: AIC_WIFI, state to: 1 [ 22.917591] aicbsp: aicbsp_set_subsys, power state change to 1 dure to AIC_WIFI [ 22.994589] aicbsp: aicbsp_platform_power_on [ 23.187483] aicbsp: aicbsp_sdio_probe:1 vid:0xC8A1 did:0x0082 [ 23.244053] aicbsp: aicbsp_sdio_probe:2 vid:0xC8A1 did:0x0182 [ 23.305583] aicbsp: aicbsp_sdio_probe after replace:1 [ 23.361598] AICWFDBG(LOGINFO) aicwf_sdio_chipmatch USE AIC8800D80 [ 23.424610] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 23.493585] aicbsp: aicwf_sdio_reg_init [ 23.548832] AICWFDBG(LOGINFO) aicbsp: aicbsp_driver_fw_init, chip rev: 7 [ 23.617611] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_patch_table_8800d80_u02.bin [ 23.766693] file md5:0c9bf9c9c10f7a90a22a4c35fa58c967 [ 23.820750] rwnx_plat_bin_fw_upload_android [ 23.864887] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_adid_8800d80_u02.bin [ 23.975753] file md5:f546881a81b960d89a672578eb45a809 [ 24.045835] rwnx_plat_bin_fw_upload_android [ 24.091587] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fw_patch_8800d80_u02.bin [ 24.302329] file md5:35d137b8a76daaeb4f5034df8e15bcde [ 24.657893] aicbt_patch_table_load bt btmode[3]:5 [ 24.671091] aicbt_patch_table_load bt uart_baud[3]:1500000 [ 24.679417] aicbt_patch_table_load bt uart_flowctrl[3]:1 [ 24.686002] aicbt_patch_table_load bt lpm_enable[3]:0 [ 24.692140] aicbt_patch_table_load bt tx_pwr[3]:28463 [ 24.755738] aicbsp: bt patch version: - Mar 07 2024 14:29:05 - git f94a3e4 [ 24.771207] rwnx_plat_bin_fw_upload_android [ 24.785752] rwnx_load_firmware :firmware path /lib/firmware/aic8800_fw/SDIO/aic8800D80/fmacfw_8800d80_u02.bin [ 24.834359] file md5:13e6f0e58aae342d260d8672ab61c31f [ 25.245654] rd_version_val06090101 [ 25.279926] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 25.286544] aicsdio: aicwf_sdio_reg_init [ 25.296102] aicbsp: aicbsp_resv_mem_alloc_skb, alloc resv_mem_txdata succuss, id: 0, size: 98304 [ 25.305423] aicbsp: aicbsp_get_feature, set FEATURE_SDIO_CLOCK 150 MHz [ 25.311997] aicbsp: sdio_err:aicwf_sdio_bus_pwrctl,1384: bus down [ 25.319135] AICWFDBG(LOGINFO) aicwf_prealloc_txq_alloc size is diff will to be kzalloc [ 25.327539] AICWFDBG(LOGINFO) aicwf_prealloc_txq_alloc txq kzalloc successful [ 25.356965] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_42 [ 25.362897] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_58 [ 25.368850] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_106 [ 25.377066] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_122 [ 25.383235] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_138 [ 25.389337] AICWFDBG(LOGERROR) invalid cmd: lvl_adj_5g_chan_155 [ 26.015672] ieee80211 phy0: HT supp 1, VHT supp 1, HE supp 1 [ 26.025301] ieee80211 phy0: ******************************************************* ** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES ** ******************************************************* [ 26.441089] rwnx_virtual_interface_add: 10, p2p-dev-wlan0 [ 26.453592] rwnx_virtual_interface_add, ifnamep2p-dev-wlan0, wdev000000006bb82764, vif_idx1 [ 26.471583] p2p dev addr1c 79 2d 96 85 74 [ 26.518513] P2P interface started3.4.2 查看sdio设备信息列出Linux内核当前通过SDIO总线检测到的所有设备[rootLS-GD ~]# ls /sys/bus/sdio/devices mmc1:42f1:1 mmc1:42f1:2其中mmc1代表设备连接在第二个MMC/SDIO控制器上这符合预期42f1这是识别出的 厂商ID(VID)1和2这是设备ID(DID)并且同一个设备在mmc1总线下有两个功能(function)。AIC8800D40是一个WiFi 蓝牙 二合一模组。因此一个典型的配置是Function 1 (这里的:1)分配给WiFi功能。Function 2 (这里的:2)分配给 蓝牙 功能。所以看到两个功能出现通常是模组工作正常的标志。3.4.3 连接wifi先运行ifconfig查看网络设备信息[rootLS-GD ~]# ifconfig eth0 Link encap:Ethernet HWaddr D6:EC:6F:2F:22:C4 inet addr:172.23.17.235 Bcast:172.23.127.255 Mask:255.255.128.0 inet6 addr: fe80::3921:fc47:7381:730d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:457 errors:0 dropped:377 overruns:0 frame:0 TX packets:113 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:32940 (32.1 KiB) TX bytes:29321 (28.6 KiB) Interrupt:147 Base address:0x8000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) wlan0 Link encap:Ethernet HWaddr 1C:79:2D:96:85:75 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)可以看到有一个有线网卡ip地址为172.23.17.235网卡名为eth0还有一个无线网卡网卡名为wlan0配置无线网nmcli dev wifi connect wifi名称 password wifi密码 ifname wlan0例如我要连接的wifi是400密码是12345678则执行以下命令[rootLS-GD ~]# nmcli dev wifi connect 400 password 12345678 ifname wlan0 Device wlan0 successfully activated with 5db07e53-0afd-4e16-ab9b-f2b80ab49a84.3.4.4 固定IP(可选)nmcli connection modify wifi名称 ipv4.method manual ipv4.addresses 192.168.1.100/24 ipv4.gateway 192.168.1.1 ipv4.dns 8.8.8.8,8.8.4.4其中IP地址后的/24是CIDR表示法将子网掩码的四个数转为2进制表示有多少个连续的1255.255.255.0有三个2558个1所以是24固定完后重新连接nmcli connection up wifi名称如果想再设置为自动获取nmcli connection modify wifi名称 ipv4.method auto设置完后重新连接nmcli connection up wifi名称3.4. 5nmcli其他用法扫描无线网nmcli device wifi list启用网络设备nmcli device connect wlan0禁用网络设备sudo nmcli device disconnect wlan0查看网络连接nmcli connection show激活网络连接nmcli connection up wifi名称停用网络连接nmcli connection down wifi名称删除网络连接:nmcli connection delete wifi名称四、代码下载loongson_2k300_lib参考文章[1]Rockchip RK3399 - WiFi AP6356驱动[2] 从零到一AIC8800 USB-WiFi模块在Linux内核6.x下的驱动适配与避坑指南[3]UGREEN AX900 (AIC8800) USB WiFi网卡Linux 6.x折腾全记录[4]AIC8800无线网卡在树莓派6.12内核下的驱动