修改dts除去sdio wifi
dts路径:kernel/arch/arm64/boot/dts/rockchip/rk3399-tve1030g.dtsi
因为为的板子上有sdio接口的wifi,如果不除去,同时有u*** wifi和sdio wifi可能会产生冲突,所以我们先disable sdio的接口的wifi。
将rtl8816的wifi驱动放到kernel里面
我们将rtl8821CU wifi驱动复制到kernel/drivers/net/wireless/rockchip_wlan/这个目录下面,同时修改当前目录下的Kconfig文件和Makefile文件。
修改Makefile将rtl8821CU添加进去(红色方框为需要添加的)。
修改Kconfig(红色方框为需要添加的)
重新编译内核
我们修改完成全部的需要修改的文件后,需要从新编译内核和安卓系统,编译成功后确认确认rtl8821.ko文件是否打包到了vendor.img。我们可以在outtargetproductrk3399vendorlibmodules目录下查看是否有8821cu.ko这个文件,如果有这个文件就证明已经打包完成。
烧录
全部工作完成后,就可以烧录全部的img,烧录完成后等待开机,然后在Android界面设置选项wifi设置那里可以搜索到wifi信号,然后就可以像正常的使用Android手机一样使用wifi上网了。
问题排查
1.首先确认u*** wifi已经正常。
如果通过lsu***,可以获取到pid和vip证明u***通讯是正常的,sdio的wifi也是这个原理,首先证明sdio和wifi上电是正常的先。
2.加载ko文件的时候可能因为疏忽,导致加载ko文件路径出错,如果加载正常,正常的log应该如下。
05-28 08:38:44.954 259 259
I -service: Wifi Hal is booting up...
05-28 08:39:03.808 399 399 I wificond: wificond is starting up...
06-03 05:44:35.551 466 466 I SystemServiceManager: Starting com.android.server.wifi.WifiService
06-03 05:44:35.724 466 466 I SystemServiceManager: Starting com.android.server.wifi.scanner.WifiScanningService
06-03 05:44:35.726 466 466 I SystemServiceManager: Starting com.android.server.wifi.p2p.WifiP2pService
06-03 05:44:35.746 466 466 D ConnectivityService: wifiOnly=true
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 0
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 2
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 3
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 4
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 5
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 10
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 11
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 12
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 15
06-03 05:44:36.369 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:44:59.016 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:45:02.142 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:45:04.605 466 466 V SettingsProvider: Notifying for 0: content://settings/global/wifi_on
06-03 05:45:04.609 259 259
wifi驱动怎么知道使用那个sdio控制器
读到这里不知道你们是不是有疑问,我们的SOC上有很多的sdio控制器,有些sdio控制器接emmc flash,有些接wifi模块,wifi驱动怎么知道我接在那个sdio控制器上呢?
其实是在wifi厂商提供的驱动里面会注册一个sdio_register_driver,当上电的时候我的emmc驱动会去扫描sdio的外围设备,当确认扫描到设备的时候会去读取设备的id即wifi模块的pid和vid,如果设备id匹配上了之后会调用使用sdio_register_driver注册进去的probe函数,从而确认我们的设备是接到那个sdio设备上。代码流程如下所示。
代码路径:kerneldriversnetwirelessrockchip_wlanrtl8189fsos_deplinuxsdio_intf.c
static const struct sdio_device_id sdio_ids[] = {
#ifdef CONFIG_RTL8723B
{ SDIO_DEVICE(0x024c, 0xB723), .driver_data = RTL8723B}, //wifi设备pid 和 vid
#endif
};
static struct sdio_drv_priv sdio_drvpriv = {
.r871xs_drv.probe = rtw_drv_init,
.r871xs_drv.remove = rtw_dev_remove,
.r871xs_drv.name = (char*)DRV_NAME,
.r871xs_drv.id_table = sdio_ids,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
.r871xs_drv.drv = {
.pm = &rtw_sdio_pm_ops,
}
#endif
};
ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv); //将wifi设备注册进sdio,sdio驱动扫描到wifi外围设备后会读取pid和vid,然后匹配上了会调用rtw_drv_init函数。
u*** wifi和sdio的wifi也是一样的,wifi模块插入u***口的时候,会读取u***模块的vid和pid,如果读取到的vid和pid和使用u***_register注册进去的设备的vid和pid是一样证明驱动匹配上了,然后调用probe函数。下面是Realtek u*** wifi部分注册代码。
代码路径:kerneldriversnetwirelessrockchip_wlanrtl8188fuos_deplinuxu***_intf.c
static struct u***_device_id rtw_u***_id_tbl[] ={
#ifdef CONFIG_RTL8188E
/*=== Realtek demoboard ===*/
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179),.driver_info = RTL8188E}, /* 8188EUS */ //u*** wifi 的pid和vid,使用匹配驱动。
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179),.driver_info = RTL8188E}, /* 8188ETV */
};
struct rtw_u***_drv u***_drv = {
.u***drv.name =(char*)DRV_NAME,
.u***drv.probe = rtw_drv_init,
.u***drv.disconnect = rtw_dev_remove,
.u***drv.id_table = rtw_u***_id_tbl,
.u***drv.suspend = rtw_suspend,
.u***drv.resume = rtw_resume,
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
.u***drv.reset_resume = rtw_resume,
#endif
#ifdef CONFIG_AUTOSUSPEND
.u***drv.supports_autosuspend = 1,
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
.u***drv.drvwrap.driver.shutdown = rtw_dev_shutdown,
#else
.u***drv.driver.shutdown = rtw_dev_shutdown,
#endif
};
ret = u***_register(&u***_drv.u***drv);
wifi射频测试之wl
射频测试的时候一般要使用一个指令wl,这个指令可以设置wifi模块的发射和接收等,然后通过综测仪等仪器可以用来测试wifi的性能,wl指令一般可以向wifi模组供应商索要,一般会给到源码,然后使用交叉编译工具链进行编译,编译好后push的Android系统中,然后使用指令进行测试。
wifi驱动排查步骤
1、linux sdio驱动无法识别(读取)wifi vendro ID硬件排查步骤。
1.1、第一步首先是排查电压,电压供电是否稳定,有没有电压被拉低的情况,一般来说wifi有如下几组电压。
VDD3.3 -> 3.3V的主电压。
DVDDIO_1.8V -> sdio IO的1.8v电压。
1.2、如果wifi模组没有晶振,时钟来自外部,则需要排查模组是否有32k的时钟输入,一般来说这个32k的时钟来自host,但是也可以使用外部的时钟芯片来提供,具体看原理图的实现。
1.3、排查chip_en脚有没有拉高。
1.4、如果上面的步骤都已经排查完毕,但是sdio驱动还是无法获取到wifi的vendor ID,可以排查别的脚是不是被别的电平干扰。
比如在调试amlogic W1芯片的时候,主控的32k接到了BT_WAKE_HOST引脚,本来这个引脚对主控来说是WIFI用来唤醒深度睡眠的HOST的,由于dts没有修改按照官方的默认配置,这个引脚输出了32k HZ的时钟,导致了W1进入了内部的测试模式,导致无法读取到vendor ID,或者sdio发送cmd没有响应。
的实现。
1.3、排查chip_en脚有没有拉高。
1.4、如果上面的步骤都已经排查完毕,但是sdio驱动还是无法获取到wifi的vendor ID,可以排查别的脚是不是被别的电平干扰。
比如在调试amlogic W1芯片的时候,主控的32k接到了BT_WAKE_HOST引脚,本来这个引脚对主控来说是WIFI用来唤醒深度睡眠的HOST的,由于dts没有修改按照官方的默认配置,这个引脚输出了32k HZ的时钟,导致了W1进入了内部的测试模式,导致无法读取到vendor ID,或者sdio发送cmd没有响应。
修改dts除去sdio wifi
dts路径:kernel/arch/arm64/boot/dts/rockchip/rk3399-tve1030g.dtsi
因为为的板子上有sdio接口的wifi,如果不除去,同时有u*** wifi和sdio wifi可能会产生冲突,所以我们先disable sdio的接口的wifi。
将rtl8816的wifi驱动放到kernel里面
我们将rtl8821CU wifi驱动复制到kernel/drivers/net/wireless/rockchip_wlan/这个目录下面,同时修改当前目录下的Kconfig文件和Makefile文件。
修改Makefile将rtl8821CU添加进去(红色方框为需要添加的)。
修改Kconfig(红色方框为需要添加的)
重新编译内核
我们修改完成全部的需要修改的文件后,需要从新编译内核和安卓系统,编译成功后确认确认rtl8821.ko文件是否打包到了vendor.img。我们可以在outtargetproductrk3399vendorlibmodules目录下查看是否有8821cu.ko这个文件,如果有这个文件就证明已经打包完成。
烧录
全部工作完成后,就可以烧录全部的img,烧录完成后等待开机,然后在Android界面设置选项wifi设置那里可以搜索到wifi信号,然后就可以像正常的使用Android手机一样使用wifi上网了。
问题排查
1.首先确认u*** wifi已经正常。
如果通过lsu***,可以获取到pid和vip证明u***通讯是正常的,sdio的wifi也是这个原理,首先证明sdio和wifi上电是正常的先。
2.加载ko文件的时候可能因为疏忽,导致加载ko文件路径出错,如果加载正常,正常的log应该如下。
05-28 08:38:44.954 259 259
I -service: Wifi Hal is booting up...
05-28 08:39:03.808 399 399 I wificond: wificond is starting up...
06-03 05:44:35.551 466 466 I SystemServiceManager: Starting com.android.server.wifi.WifiService
06-03 05:44:35.724 466 466 I SystemServiceManager: Starting com.android.server.wifi.scanner.WifiScanningService
06-03 05:44:35.726 466 466 I SystemServiceManager: Starting com.android.server.wifi.p2p.WifiP2pService
06-03 05:44:35.746 466 466 D ConnectivityService: wifiOnly=true
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 0
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 2
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 3
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 4
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 5
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 10
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 11
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 12
06-03 05:44:35.746 466 466 D ConnectivityService: networkAttributes - ignoring mobile as this dev is wifiOnly 15
06-03 05:44:36.369 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:44:59.016 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:45:02.142 466 485 E BatteryExternalStatsWorker: no controller energy info supplied for wifi
06-03 05:45:04.605 466 466 V SettingsProvider: Notifying for 0: content://settings/global/wifi_on
06-03 05:45:04.609 259 259
wifi驱动怎么知道使用那个sdio控制器
读到这里不知道你们是不是有疑问,我们的SOC上有很多的sdio控制器,有些sdio控制器接emmc flash,有些接wifi模块,wifi驱动怎么知道我接在那个sdio控制器上呢?
其实是在wifi厂商提供的驱动里面会注册一个sdio_register_driver,当上电的时候我的emmc驱动会去扫描sdio的外围设备,当确认扫描到设备的时候会去读取设备的id即wifi模块的pid和vid,如果设备id匹配上了之后会调用使用sdio_register_driver注册进去的probe函数,从而确认我们的设备是接到那个sdio设备上。代码流程如下所示。
代码路径:kerneldriversnetwirelessrockchip_wlanrtl8189fsos_deplinuxsdio_intf.c
static const struct sdio_device_id sdio_ids[] = {
#ifdef CONFIG_RTL8723B
{ SDIO_DEVICE(0x024c, 0xB723), .driver_data = RTL8723B}, //wifi设备pid 和 vid
#endif
};
static struct sdio_drv_priv sdio_drvpriv = {
.r871xs_drv.probe = rtw_drv_init,
.r871xs_drv.remove = rtw_dev_remove,
.r871xs_drv.name = (char*)DRV_NAME,
.r871xs_drv.id_table = sdio_ids,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
.r871xs_drv.drv = {
.pm = &rtw_sdio_pm_ops,
}
#endif
};
ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv); //将wifi设备注册进sdio,sdio驱动扫描到wifi外围设备后会读取pid和vid,然后匹配上了会调用rtw_drv_init函数。
u*** wifi和sdio的wifi也是一样的,wifi模块插入u***口的时候,会读取u***模块的vid和pid,如果读取到的vid和pid和使用u***_register注册进去的设备的vid和pid是一样证明驱动匹配上了,然后调用probe函数。下面是Realtek u*** wifi部分注册代码。
代码路径:kerneldriversnetwirelessrockchip_wlanrtl8188fuos_deplinuxu***_intf.c
static struct u***_device_id rtw_u***_id_tbl[] ={
#ifdef CONFIG_RTL8188E
/*=== Realtek demoboard ===*/
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179),.driver_info = RTL8188E}, /* 8188EUS */ //u*** wifi 的pid和vid,使用匹配驱动。
{USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179),.driver_info = RTL8188E}, /* 8188ETV */
};
struct rtw_u***_drv u***_drv = {
.u***drv.name =(char*)DRV_NAME,
.u***drv.probe = rtw_drv_init,
.u***drv.disconnect = rtw_dev_remove,
.u***drv.id_table = rtw_u***_id_tbl,
.u***drv.suspend = rtw_suspend,
.u***drv.resume = rtw_resume,
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
.u***drv.reset_resume = rtw_resume,
#endif
#ifdef CONFIG_AUTOSUSPEND
.u***drv.supports_autosuspend = 1,
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
.u***drv.drvwrap.driver.shutdown = rtw_dev_shutdown,
#else
.u***drv.driver.shutdown = rtw_dev_shutdown,
#endif
};
ret = u***_register(&u***_drv.u***drv);
wifi射频测试之wl
射频测试的时候一般要使用一个指令wl,这个指令可以设置wifi模块的发射和接收等,然后通过综测仪等仪器可以用来测试wifi的性能,wl指令一般可以向wifi模组供应商索要,一般会给到源码,然后使用交叉编译工具链进行编译,编译好后push的Android系统中,然后使用指令进行测试。
wifi驱动排查步骤
1、linux sdio驱动无法识别(读取)wifi vendro ID硬件排查步骤。
1.1、第一步首先是排查电压,电压供电是否稳定,有没有电压被拉低的情况,一般来说wifi有如下几组电压。
VDD3.3 -> 3.3V的主电压。
DVDDIO_1.8V -> sdio IO的1.8v电压。
1.2、如果wifi模组没有晶振,时钟来自外部,则需要排查模组是否有32k的时钟输入,一般来说这个32k的时钟来自host,但是也可以使用外部的时钟芯片来提供,具体看原理图的实现。
1.3、排查chip_en脚有没有拉高。
1.4、如果上面的步骤都已经排查完毕,但是sdio驱动还是无法获取到wifi的vendor ID,可以排查别的脚是不是被别的电平干扰。
比如在调试amlogic W1芯片的时候,主控的32k接到了BT_WAKE_HOST引脚,本来这个引脚对主控来说是WIFI用来唤醒深度睡眠的HOST的,由于dts没有修改按照官方的默认配置,这个引脚输出了32k HZ的时钟,导致了W1进入了内部的测试模式,导致无法读取到vendor ID,或者sdio发送cmd没有响应。
的实现。
1.3、排查chip_en脚有没有拉高。
1.4、如果上面的步骤都已经排查完毕,但是sdio驱动还是无法获取到wifi的vendor ID,可以排查别的脚是不是被别的电平干扰。
比如在调试amlogic W1芯片的时候,主控的32k接到了BT_WAKE_HOST引脚,本来这个引脚对主控来说是WIFI用来唤醒深度睡眠的HOST的,由于dts没有修改按照官方的默认配置,这个引脚输出了32k HZ的时钟,导致了W1进入了内部的测试模式,导致无法读取到vendor ID,或者sdio发送cmd没有响应。
举报