一、SDIO 设备驱动移植
(1)修改SD卡驱动使内核支持SD卡
修改文件:arch/arm/mach-s3c2410/mach-smdk2410.c
添加所需头文件:
#include<mach/gpio.h>
#include<linux/mmc/host.h>
#include<plat/mci.h>
//增加平台设备对sd卡的支持
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_ohci,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_sdi,
};
添加平台数据dev->platform_data
Static struct s3c24xx_mci_pdata smdk2410_mmc_cfg__initdata={
.gpio_detect = S3C2410_GPG(10),
.set_power = NULL,
.ocr_avail = MMC_VDD_32_33,
};
(2)在smdk2410_init中添加
S3c24xx_mci_set_platdata(&smdk2410_mmc_cfg);
二、配置内核以支持Marvel无线WIFI
选择35内核中的wlan marwell sdio模块
device drivers ----> |
三、编译内核,生成驱动模块
(1)先执行make 然后make modules //内核生成模块的方式
(2)将生成的wlan相关ko文件拷贝到目标板中,在这我放在/sdio目录下
home/kernel/linux-2.6.35/drivers/net/wireless/libertas/$ cp libertas.ko libertas_sdio.ko /rootfs/filesystem/sdio/
/rootfs/filesystem/sdio$ls
libertas.ko libertas_sdio.ko
(3)把固件helper_sd.bin sd8686.bin拷贝到相应的位置/rootfs/filesystem/lib/firmware/mrvl/ (Android中wifi.c有定义,属于HAL层,后面两个目录是自己创建的)
(4)在目标板子插入SDIO WIFI 并加载驱动
首先插入SDIO WIFI 然后加载驱动
/sdio#insmod libertas.ko
/sdio#insmod libertas_sdio.ko helper_name=/lib/firmware/mrvl/helper_sd.bin fw_name=/lib/firmware/mrvl/sd8686.bin (注意要在一行)
驱动加载完成会提示:(注意:如果没有,则再次热插拔你的sdio wifi卡便可以看到)
if_sdio_intterupt
libertas: 00:01:36:19:b3:6b, fw 9.70.3p23, cap 0x00000303
if_sdio_intterupt
libertas: wlan0: Marvell WLAN 802.11 adapter
sdio_havefister_driver
sdio_init_module have done
四、制作无线测试工具
测试无线网卡用无线工具iwconfig iwlist等命令是通过开源软件wireless_tools_29.rar编译得到。
步骤:
(1)首先在windows目录解压上面那个软件包,把解压后的文件夹复制到虚拟机/home$ls
wireless_tools_29
/home/wireless_tools_29$
(2)修改Makefile
8 PREFIX = /home/wtools //指定安装路径 12 CC = arm-linux-gnu-gcc (和编译你的文件系统所用保持一致,也可静态编译,对Makefile适当修改) 14 AR = arm-linux-gnu-ar |
lib sbin usr
目录,libiw.so(这是个软连接) libiw.so.29库在lib目录 而sbin目录为一些网络工具,如:iwlist、iwconfig等 可以man xxx查看功能
(3)拷贝libiw.so、libiw.so.29库和测试工具
/home/wtools/lib/$ cp * /rootfs/filesystem/lib -a
/home/wtools/sbin/$ cp * /rootfs/filesystem/bin (这样就不用考虑环境变量了)
五、测试
ifconfig -a 查看是否检测到无线网卡
在测试工具目录下测试
/sdio/wtools# ifconfig wlan0 up
/sdio/wtools# iwlist wlan0 scanning //搜索热点
/sdio/wtools# iwconfig wlan0 essid "FS241" //链接热点
/sdio/wtools# ifconfig wlan0 192.168.1.99 netmask 255.255.255.0 up (静态分配,也可以动态分配。参考我的《基于FS2410的DHCP移植》)
/sdio/wtools# route add default gw 192.168.1.1
/sdio/wtools# ping 192.168.1.1 (测试ping通后,就可以接着给它加密了)
待更新……
-
linux下移植之WIFI驱动2010-05-14 22:271. 前言
硬件平台: imx27+sd8686
软件平台: linux
内核: 2.6.27
2. 移植思想
1, WIFI 模块本身和 cpu 之间的接口;
我们的模块和 cpu 之间的接口是 sdio 的,也就是说必须要先保证 SDIO 本身是工作的,与SD卡,MMC属于同类型。 主要用到这几个GPIO引脚SD0...SD3,SD2_CMD,SD2_CLK,以及复位引脚PB24.
2, WIFI 模块本身的上电时序;
模块都有它自己的规律,所以必须要根据 spec 了解它本身的上电过程,严格遵守;
3, 以太网接口的创建;
我们的 WIFI 模块本身是建立在 SDIO 口之上的,而对上都是提供以太网接口的,所以必须要保证这个接口以及创建;
4, 特殊处理;
不同的模块都有它特别的地方,比如我们用的是 8686 和 compo 也就是说它和蓝牙共用天线,所以需要在初始化的时候做特殊的处理,发送特殊的命令,才能工作;
3. 移植过程
1, sdio 本身是通过 gpio 口模拟的,所以需要对 gpio 口进行配置 ;
static mfp_cfg_t littleton_mmc3_pins[] = {
GPIO7_2_MMC3_DAT0,
GPIO8_2_MMC3_DAT1,
GPIO9_2_MMC3_DAT2,
GPIO10_2_MMC3_DAT3,
GPIO103_MMC3_CLK,
GPIO105_MMC3_CMD,
};
2, wifi 模块本身的初始化 ;
#define MFP_WIFI_V18_ENABLE (GPIO26_GPIO)
#define MFP_WLAN_RESETN (GPIO99_GPIO)
#define WIFI_WAKEUP_HOST (GPIO104_GPIO) /*error must be changed*/
#define WLAN_ENABLE_PIN 26
#define WLAN_RESET_PIN 99
#define M200_B
#ifdef M200_B
#define BT_RESET_PIN EXT1_GPIO(1)
#define BT_RESET_GPIO (GPIO1_2_GPIO)
#else
#define BT_RESET_GPIO (GPIO6_2_GPIO)
#define BT_RESET_PIN EXT1_GPIO(6)
#endif
static mfp_cfg_t lin2008_wifibt_pins[] = {
MFP_WIFI_V18_ENABLE,
MFP_WLAN_RESETN,
WIFI_WAKEUP_HOST,/*wakeup host*/
};
static mfp_cfg_t lin2008_wifibt_pins2[] = {
MFP_WIFI_V18_ENABLE,
};
static int wifibt_power_status;
int lin2008_poweron_wifibt_board(void)
{
if (!wifibt_power_status) {
mxc_mfp_config(ARRAY_AND_SIZE(lin2008_wifibt_pins));
gpio_direction_output(WLAN_ENABLE_PIN, 1);
gpio_direction_output(WLAN_RESET_PIN, 1);
gpio_direction_output(BT_RESET_PIN,1);
mdelay(10);
gpio_direction_output(BT_RESET_PIN, 0);
gpio_direction_output(WLAN_RESET_PIN, 0);
// bt need > 5 ms to reset
mdelay(5);
gpio_direction_output(BT_RESET_PIN, 1);
gpio_direction_output(WLAN_RESET_PIN, 1);
wifibt_power_status++;
return 0;
}
wifibt_power_status++;
return 1;
}
int lin2008_poweroff_wifibt_board(void)
{
wifibt_power_status--;
if (!wifibt_power_status) {
mxc_mfp_config(ARRAY_AND_SIZE(lin2008_wifibt_pins2));
gpio_direction_output(WLAN_ENABLE_PIN, 0);
return 0;
}
return 1;
}
3, 以太网接口的创建
这里在 android 平台上要做特殊的处理,也就是 firmware 的位置要放好,否则加载 firmware 始终不成功,那么以太网接口就不会被创建了;
需要把 helper_sd.bin 放在 /lib/firmware/mrvl 下面(若没有,则创建一个);
把 sd8686.bin 放在 /lib/firmware/mrvl 下面(同上);
4, 特殊的处理
对于 8686 模块需要做特殊的处理,在注册完以太网接口以后,需要添加下面这段话 :
{
#define BCA_CFG_NUM_OF_MODES 4
#define BCA_CFG_SINGLE_ANT_WITH_COEX 0
#define BCA_CFG_DUAL_ANT_WITH_COEX 1
#define BCA_CFG_SINGLE_ANT_FOR_BT_ONLY 2
#define BCA_CFG_MRVL_DEFAULT 3
#define BCA_CONFIG BCA_CFG_SINGLE_ANT_WITH_COEX
static u32 BCACfgTbl[BCA_CFG_NUM_OF_MODES][3] = {
//0xA5F0, 0xA58C, 0xA5A0
{ 0xa027181c, 0x40214, 0xd24d}, //Mode 0: Single ANT with COEX enable
{ 0xa027181c, 0x40211, 0xd24d}, //Mode 1: Dual ANT with COEX enable
{ 0xa027181c, 0x40222, 0xd21c}, //Mode 2: single ANT for BT only
{ 0xa027801d, 0x18000, 0xd21c}, //Mode 3: Marvell default
};
wlan_offset_value RegBuffer;
RegBuffer.offset = (0xA5F0);
RegBuffer.value = BCACfgTbl[BCA_CONFIG][0];
wlan_prepare_cmd(priv,
HostCmd_CMD_MAC_REG_ACCESS,
HostCmd_ACT_GEN_SET,
HostCmd_OPTION_WAITFORRSP,
0,&RegBuffer);
RegBuffer.offset =(0xA58C);
RegBuffer.value = BCACfgTbl[BCA_CONFIG][1];
wlan_prepare_cmd(priv,
HostCmd_CMD_MAC_REG_ACCESS,
HostCmd_ACT_GEN_SET,
HostCmd_OPTION_WAITFORRSP,
0,&RegBuffer);
RegBuffer.offset = (0xA5A0);
RegBuffer.value = BCACfgTbl[BCA_CONFIG][2];
wlan_prepare_cmd(priv,
HostCmd_CMD_MAC_REG_ACCESS,
HostCmd_ACT_GEN_SET,
HostCmd_OPTION_WAITFORRSP,
0,&RegBuffer);
}
基本上这样就可以工作了;
4. 其它问题
Sdio 口默认是用的 3.2V 这里需要修改相关的地方强制设成是 1.8V ,否则 SDIO 接口将无法工作;
Linux平台上需要移植一些上层软件才能验证,比如 iwconfig , iwlist 等。
测试步骤:
ifconfig eth0 up
iwlist eth0 scanning
如果能扫描到 AP 那么证明基本已经 OK 了;
iwconfig eth0
iwlist eth0 freq
可以查看设备的相关信息,查看各项是否正常。
现在,就可以 ping 通 IP 地址了;
5. 常见问题
1, WIFI 驱动注册 sdio 驱动的时候出错,也就是 probe 函数未被调用?
需要检查 sdio 设备本身是否被检测到,内核是通过发送特定的命令来检测是 sdio 是 SD 卡还是 mmc 的,
在 mmc_rescan 函数里面可以看到 sdio 设备的加载过程,有可能就是你的电压设置不对;
2, 以太网接口一直出不来或者说 firmware 加载失败?
这里需要确保 firmware 是否正确被加载,很可能是它找不到对应的 firmware ,可以通过添加打印信息看看,它的路径到底是在什么地方,对于 wifi 来说 helper_sd.bin 需要放在 /lib/firmware/ 下面,而 sd8686.bin 需要放在 /lib/firmware/mrvl 下面;
3, 一切正常,但是调用 iwlist eth0 scanning 的时候,扫描不到任何结果,出现NO scan results?
这时候需要做特殊的处理,比如共存代码的设置,是否正常等,通常可以判断有没有中断上来,以此区分到底是模块和cpu 的连接问题还是模块本身的设置问题;
4, 工作一段时间后不正常
这个有可能是蓝牙模块需要进行初始化,因为它们是共用天线,有时候不起蓝牙模块对应的 40M 时钟就不起来;
本人参照:http://blog.chinaunix.net/u2/67984/showart_2113942.html 此博客而移植成功的。
在此感谢wylhistory!
目前sourceforge网站上提供了Linux 2.6.18版本内核的sdiostack补丁,使用此补丁后可以编译出供Atheros SDIO wifi v1.0模块使用的驱动。
首先选择工作目录(例如当前用户的个人目录/home/~),此后的操作都在此目录下进行。下面以Samsung S3C2410平台为例介绍驱动编译过程,使用的交叉编译工具为arm-linux-gcc v3.4.6。
1. 下载内核压缩包并解压。
tar zxvf linux-2.6.18.tar.gz
2. 下载sdiostack驱动并解压至内核源码目录,补丁包含5个patch文件和1个series文件,按照series文件中的顺序依次打补丁。
tar zxvf sdio-linux-2.6.18.tar.gz -C linux-2.6.18/
cd linux-2.6.18/
patch -p1 < common_atheros_sdiostack.patch
patch -p1 < common_atheros_sdiostack_shcd.patch
patch -p1 < common_atheros_sdiostack_functions.patch
patch -p1 < common_atheros_sdiostack_sample_fd.patch
patch -p1 < common_atheros_sdiostack_benchmark.patch
patch -p1 < common_atheros_sdiostack_ar6000_wlan.patch
3. 可以从配置路径拷贝s3c2410配置模板后再对其修改。
cp arch/arm/configs/s3c2410_defconfig .config
需要开启Device Drivers-->Plug and Play support-->Plug and Play support选项支持PnP。
需要开启Device Drivers-->Network device support-->Wireless LAN (non-hamradio)--> Wireless LAN drivers (non-hamradio) & Wireless Extensions选项,否则无法找到wireless_send_event函数定义。
make menuconfig
4. drivers/pnp/resource.c中的request_dma和free_dma函数需要删除,不然在稍后的编译中会造成缺少定义的错误(我始终未能让resource.c成功的找到这两个相关的dma函数实现,最后只能注释掉了,如果有了解的朋友,希望能告诉我正确的做法)。然后开始内核编译操作。
make
5. 最后在drivers/sdio/对应目录下生成驱动各个模块。sdiostack补丁中只提供了很少几种平台的hcd模块代码,如果缺少对应目标平台的代码,还需要自己移植。以下4个模块为必须的最小配置。
lib/sdio_lib.ko
busdriver/sdio_busdriver.ko
function/wlan/ar6000/ar6000.ko
hcd/s3c2412/sdio_s3c2410_hcd.ko
注意:编译sdiostack驱动时使用的内核版本需要和目标平台上的内核版本一致,如果不是2.6.18版本的内核,在打补丁过程中可能会有提示信息,可以根据提示信息手工修改。不同平台的内核配置选项也会有所不同,可能需要对配置做少许调整。一般来说,补丁中包含的hcd模块代码不能满足需要,所以要想最终能使用SDIO WIFI网卡,最困难的地方在于如何获取缺少的这一部分的代码。MontaVista也提供了一个补丁下载,我没有用过这个补丁,但是其中包含的sdiostack文档是很好的资料。如果希望使用Atheros SDIO wifi v2.0,可以看看openmoko补丁。下一步,我将尝试编译wifi v2.0的驱动。