CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308

CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308


文章目录

  • CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308
  • 前言
  • 一、SSV6256驱动包
  • 二、移植步骤
    • 1.将ssv驱动引入rk3308 SDK
    • 2.将SSV驱动引入RK3308编译环境
    • 3.ssv驱动配置以及添加网络唤醒功能
      • 1>内核配置
      • 2>增加p2p interface,用于AP模式使用这个网卡
      • 3>网络唤醒
    • 4.其他
  • 总结


前言

目前5G wifi越来越普及,给需要无线联网的设备添加5G wifi模块成为一种必要,尤其在iot物联网,5G wifi速度和连接数都相对2.4G有巨大的优势,所以这里用5G wifi模块ssc6256的驱动移植来引入嵌入式linux的学习


一、SSV6256驱动包

使用哪家的wifi模块,一般会有供应商提供驱动包,我这里有我使用的驱动包,链接如下:
链接: ssv6256驱动包

二、移植步骤

大部分操作在<南方硅谷ssv6x5x 驱动移植用户指南.doc>中也有说明,我这里对一些细节进行补充

1.将ssv驱动引入rk3308 SDK

驱动包中有个压缩包,其中LSMAC.19Q3.2126.02就是ssv6x5x原始驱动
CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308_第1张图片
将LSMAC.19Q3.2126.02解压出来,文件夹改名为ssv6256,然后放到rk3308的sdk下

./kernel/drivers/net/wireless/rockchip_wlan/ssv6256

CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308_第2张图片
就此ssv的驱动就引入到rk3308的sdk中了


2.将SSV驱动引入RK3308编译环境

为了让RK3308的编译系统能直接编译ssv驱动,需要修改相关Makefile和Kconfig
ssv6256驱动是放在"./kernel/drivers/net/wireless/rockchip_wlan/"目录下,所以需要修改rockchip_wlan目录下的Makefile和Kconfig


rockchip_wlan/Kconfig需要添加:

source “drivers/net/wireless/rockchip_wlan/ssv6256/Kconfig”

将ssv6256/Kconfig包含进系统

ssv6256/Kconfig内容如下

#menu "iComm-semi 6X5X WLAN support"
config SSV6X5X
	tristate "SSV6X5X Wireless driver"
	depends on MAC80211 && MMC
	---help---
		Enable iComm-semi SSV6X5X WLAN kernel driver.

#endmenu

这样make menuconfig中将会有SSV6X5X的选项
对应到Makefile中,就是CONFIG_SSV6X5X


rockchip_wlan/Makefile需要添加:

obj-$(CONFIG_SSV6X5X) += ssv6256/

表示如果有定义CONFIG_SSV6X5X,就添加./ssv6256目录进行编译


rockchip_wlan/ssv6256/Makefile需要添加:

#获取当前makefile的绝对路径
LAST_MAKEFILE_PATH :=$(abspath $(lastword $(MAKEFILE_LIST)))
#获取当前makefile所在文件夹的绝对路径
SSV_DRV_PATH := $(dir $(LAST_MAKEFILE_PATH))

用来给ssv的makefile定位自己的所在位置,让ssv驱动正确的编译
如果不添加这句,$(PWD)获取的就是rk3308编译脚本所在的目录会导致编译异常
CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308_第3张图片


最后复制驱动到sdk的时候ssv6256目录下的parser-conf.sh可能会权限异常,无法执行,需要修改权限

cd ./kernel/drivers/net/wireless/rockchip_wlan/ssv6256
chmod 777 ./parser-conf.sh


然后这个时候在make menuconfig中将SSV6X5X设置为M,或者在defconfig中添加

CONFIG_SSV6X5X=m

就可以将ssv的驱动编译成ko文件了
当然也可以直接设置成y,打包进linux系统中,但是打包进内核需要确认stacfgpath和code相关默认配置
具体可以看驱动包中的<南方硅谷ssv6x5x 驱动移植用户指南.doc>


3.ssv驱动配置以及添加网络唤醒功能

1>内核配置

内核需要支持MAC80211和cfg80211,我直接设置成y,编译进内核中


2>增加p2p interface,用于AP模式使用这个网卡

需要在linux/net/mac80211/main.c中添加:

/* add one default STA interface if supported */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) 
{
	result = ieee80211_if_add(local, "wlan%d", NULL,NL80211_IFTYPE_STATION, NULL);
	if (result)
	wiphy_warn(local->hw.wiphy,"Failed to add default virtual iface\n");
}
/*增加*/
if (local->hw.wiphy->interface_modes 
		& (BIT(NL80211_IFTYPE_P2P_GO)|BIT(NL80211_IFTYPE_P2P_CLIENT))) 
{
	result = ieee80211_if_add(local, "p2p%d", NULL,NL80211_IFTYPE_STATION, NULL);
	if (result)
	wiphy_warn(local->hw.wiphy,"Failed to add default virtual iface\n");
}

就会在驱动加载后多一个p2p0网卡,可用于打开ap热点
CL嵌入式linux学习:第一章 SSV6256wifi驱动移植到RK3308_第4张图片


3>网络唤醒

网络唤醒主要需要修改./ssv6x5x-generic-wlan.c文件
主要就是在模块初始化接口中,添加唤醒中断的注册,然后休眠后,wifi模块收到网络信号,就会拉高wifi唤醒引脚,然后触发系统唤醒中断,让系统唤醒.

#include 
#include 
#include 
#include 
#include 
#include 

extern int get_wifi_chip_type(void);
extern int rockchip_wifi_power(int on);
extern int rockchip_wifi_set_carddetect(int val);
static struct wake_lock ssv6x5x_wlock;	//唤醒锁
unsigned int oob_irq;					//wifi中断句柄
/*
 * wifi唤醒引脚中断的回调函数 
 */
static irqreturn_t gpio_hostwakeup_irq_thread(int irq, void *data)
{
	printk(KERN_INFO "gpio_hostwakeup_irq_thread\n");
	wake_lock_timeout(&ssv6x5x_wlock, (HZ/2));	//阻止系统休眠,0.5s后自动释放
	//android_lock_suspend_auto_expire(&rtw_suspend_lock, rtw_ms_to_systime(timeout_ms));
	return IRQ_HANDLED;
}
//驱动模块初始化入口
static int generic_wifi_init_module(void)
{
	int err;
	u32 status = 0;
	wake_lock_init(&ssv6x5x_wlock, WAKE_LOCK_SUSPEND, "ssv6x5x_wakelock");
	oob_irq = rockchip_wifi_get_oob_irq();	//获取wifi唤醒中断句柄,这个中断在设备树中配置
	if (oob_irq == 0)
	{
		printk(KERN_INFO "oob_irq ZERO!\n");
		return -1;
	}
	enable_irq_wake(oob_irq);	//使能中断唤醒功能,rk3308只有gpio0的中断才支持休眠唤醒
	printk(KERN_INFO "%s : oob_irq = %d\n", __func__, oob_irq);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
	status = IRQF_NO_SUSPEND;
#endif
	/*高电平有效为1,低电平有效为0
	 *ssv模块内部没有可以配置引脚默认电平的地方,所以这里都是应该设置为高电平有效
	 */
	if (1)
	{
		status |= IRQF_TRIGGER_RISING;	//上升沿触发中断
	}
	else
	{
		status |= IRQF_TRIGGER_FALLING; //下降沿触发中断
	}
	err = request_threaded_irq(oob_irq, gpio_hostwakeup_irq_thread, NULL,
				   status, "rtw_wifi_gpio_wakeup", (void*)1);
	if (err < 0)
	{
		printk(KERN_INFO "Oops: can't allocate gpio irq %d err:%d\n", oob_irq, err);
		return -1;
	}
	else 
	{
		printk(KERN_INFO "allocate gpio irq %d ok\n", oob_irq);
	}
	
	return initWlan();		//原本只有这一句,上面的都是添加的,用来wifi唤醒
}
//模块卸载出口
static void generic_wifi_exit_module(void)
{
	exitWlan();	//原来自由这一句,下面都是添加的,用来释放wifi唤醒相关资源
	if (oob_irq == 0)
		return;
	free_irq(oob_irq, (void*)1);
	disable_irq_wake(oob_irq);
	wake_lock_destroy(&ssv6x5x_wlock);
}

// #ifdef CONFIG_SSV6X5X //CONFIG_SSV6XXX=y	//注释掉原来的
#if 0
late_initcall(generic_wifi_init_module);	//因为我是设置成m,作为模块使用,所以去掉这个系统初始化接口注册
#else //CONFIG_SSV6XXX=m or =n
module_init(generic_wifi_init_module);
#endif
module_exit(generic_wifi_exit_module);

MODULE_LICENSE("Dual BSD/GPL");

wifi唤醒gpio的设置在设备树中,我这里使用的是GPIO0 PA0
提示:rk3308只有gpio0才能支持wifi唤醒

/ {
	wireless_wlan: wireless-wlan {
		compatible = "wlan-platdata";
		rockchip,grf = <&grf>;
		pinctrl-names = "default";
		pinctrl-0 = <&wifi_wake_host>;
		wifi_chip_type = "rtl8189es";
		WIFI,host_wake_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};
};
&pinctrl {
	wireless-wlan {
		wifi_wake_host: wifi-wake-host {
			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

然后根据
在./ssv6x5x-wifi.cfg中添加

lp_wakeuppin = 1
#lp_keepalive = 120000
fw_reset = 0
powermode = 4
#lp_beaconloss_maxcnt = 10
#lp_beaconloss_guard = 40
#lp_dataretx_guard = 40
lp_userdtim = 3

并确定wif模块晶振频率

xtal_clock = 24

最后将ssv6x5x-wifi.cfg和编译好的复制打包到文件系统中
开机运行

insmod ssv6x5x.ko stacfgpath=/home/ssv6x5x-wifi.cfg

然后驱动基本移植完成,具体细节可以看<南方硅谷ssv6x5x 驱动移植用户指南.doc>

4.其他

在实际使用中发现ssv6256需要提前供电,可能是必须要在sdio初始化前就让ssv6256上电,我是修改到了uboot初始化的时候,对ssv6256的使能引脚进行了初始化


其次sta模式和ap模式必须再同一频段才能共存,否则在sta模式下用hostapd是打不开ap模式的

总结

以上就是一直ssv6256到rk3308的过程,其他wifi驱动也大同小异,重点需要注意的就是wifi唤醒和模块上电逻辑,处理不好会有一些奇怪的问题,然后wifi唤醒最好是多个路由器尝试,有些路由器可能会有唤醒不了的情况,换个路由器就正常了,具体原因没有深究,有大佬知道原因,可以互相交流下

你可能感兴趣的:(linux驱动,嵌入式linux,嵌入式,linux,驱动开发,iot,嵌入式硬件)