iTOP4412开发板采用的是Linux 3.0.15 版本,MTK官方给的移植Porting没有说明针对具体的 kernel版本,由于是Android4.4,所以kernel应该是3.0以后的版本或者更高支持;
首先按照PoringGuid的指导说明,把New和Modify文件夹下面关于kernel部分的修改放到我们的kernel代码里面,MT6620的驱动分两个部分, 一部分放在driver/misc/目录下面,文件夹名称 mediatek,里面存放的是WMT,既wirelessmanage tools, 里面提供了与MT6620 download firmware patch ,enable /disable WIFi芯片,power on,power off操作的相关驱动部分, 及SDIO总线设备接口驱动Host Interface drivers,这些驱动工作正常后才开始加载WiFi 网络相关驱动。
我们以驱动库 .ko 的形式编译驱动模块,driver/misc/mediatek/库文件与WiFi网络库文件列表如下::
mtk_hif_sdio.ko ----mmc总线相关接口,mmc总线发现SDIO设备,分配总线地址后,会与该驱动进行适配.适配成功后该驱动会调用WiFi网络驱动;
mtk_stp_uart.ko-----串口相关驱动,通过串口下载固件补丁,设置芯片参数;
mtk_stp_wmt.ko-----core 部分,提供WiFi上电,断电等等相关操作;
mtk_wmt_wifi.ko ----字符设备驱动,创建设备节点用于与用户空间交互;
wlan_mt6620.ko -- -- WiFi网络相关驱动,不需要我们进行修改;
另外这里附一张MMC驱动框架图:
因为我们的MT6620模块挂载到了MMC总线上面,属于MMC子系统的工作实例,我们非常有必要熟悉一下mmc驱动架构,是我们移植工作的非常重要的一部分,关于MMC子系统的详细介绍这里不再说明.
1 根据硬件连接情况配置必要的平台资源
修改文件: kernel/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c
关键函数1: 该函数配置WiFi相关的GPIO引脚为初始化输出状态,或者配置为中断状态
WIFI驱动会改变这些引脚的状态,这里仅仅是初始化.
static void __init mtk_combo_init(void)
{
//MT66XX PMUEN
if(gpio_request(EXYNOS4_GPC1(0),"GPC1_0"))
{
printk(KERN_ERR "failed torequest GPC1_0 for MT6620 PMUEN control\n");
}
//MT66XX SYSRST
if(gpio_request(EXYNOS4_GPC1(1),"GPC1_1"))
{
printk(KERN_ERR "failed to requestGPC1_1 for MT6620 SYSRSTcontrol\n");
}
s3c_gpio_cfgpin(EXYNOS4_GPC1(0),S3C_GPIO_OUTPUT);
s3c_gpio_cfgpin(EXYNOS4_GPC1(1),S3C_GPIO_OUTPUT);
gpio_direction_output(EXYNOS4_GPC1(0),0);
gpio_direction_output(EXYNOS4_GPC1(1),0);
gpio_free(EXYNOS4_GPC1(0));
gpio_free(EXYNOS4_GPC1(1));
mdelay(5);
//need config eint models for Wifi& BGA Interupt
if (gpio_request(EXYNOS4_GPX2(5),"WiFi INT"))
printk(KERN_WARNING"MT6620 WiFi INT(GPX2.5) Port request error!!!\n");
else {
s3c_gpio_setpull(EXYNOS4_GPX2(5),S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(EXYNOS4_GPX2(5), S3C_GPIO_SFN(0xF));
gpio_free(EXYNOS4_GPX2(5));
}
if (gpio_request(EXYNOS4_GPX2(4),"BGF INT"))
printk(KERN_WARNING"MT6620 BGA INT(GPX2.4) Port request error!!!\n");
else {
s3c_gpio_setpull(EXYNOS4_GPX2(4), S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(EXYNOS4_GPX2(4), S3C_GPIO_SFN(0xF));
gpio_free(EXYNOS4_GPX2(4));
}
//normal it is high level
if (gpio_request(EXYNOS4_GPX3(2), "6260_GPIO2")!=0) {
printk("[mt6620] ERROR:Cannotrequest 6260_GPIO2\n");
} else {
gpio_direction_output(EXYNOS4_GPX3(2), 1);/* WLAN_CHIP_PWD */
gpio_set_value(EXYNOS4_GPX3(2),1);
mdelay(100);
gpio_free(EXYNOS4_GPX3(2));
}
return; }
关键函数2: setup_mt6620_wlan_power_for_onoff
该函数为导出函数,WIFi驱动会调用该函数,该函数关键地方是让MMC控制器驱动扫描MMC总线上面的设备,MMC扫描到了WiFI模块才会加载相应的WiFi驱动,这里是主动让MMC扫描,我们的SD卡是采用中断触发的方式扫描,他们本质上都是扫描MMC总线上面的新设备,然后加载对应的设备驱动,具体的可以看一下MMC子系统相关内容.
函数所属文件: kernel/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c
voidsetup_mt6620_wlan_power_for_onoff(int on)
{
int chip_pwd_low_val;
int outValue;
printk("[mt6620] +++ %s : wlan power%s\n",__func__, on?"on":"off");
#if 1
if (on) {
outValue = 0;
} else {
outValue = 1;
}
if (gpio_request(EXYNOS4_GPX3(2), "6260_GPIO2")!=0) {
printk("[mt6620] ERROR:Cannotrequest 6260_GPIO2\n");
} else {
gpio_direction_output(EXYNOS4_GPX3(2),1);/* WLAN_CHIP_PWD */
gpio_set_value(EXYNOS4_GPX3(2),outValue);
mdelay(100);
gpio_free(EXYNOS4_GPX3(2));
}
if(on)
{
//need reset on mt6620 ? need test......
}
#endif
extern voidsdhci_s3c_sdio_card_detect(struct platform_device *pdev);
// mdelay(200);
//need sdhc controler check wifi catdstates......
sdhci_s3c_sdio_card_detect(&s3c_device_hsmmc3);
printk("[mt6620] ---%s\n",__func__);
}
EXPORT_SYMBOL(setup_mt6620_wlan_power_for_onoff);
关键结构体: 该结构体告诉WiFi驱动相关部分使用了平台的哪些GPIO资源.
结构体所属文件: kernel/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c
static struct mtk_wmt_platform_datamtk_wmt_pdata = {
.pmu =EXYNOS4_GPC1(0),//RK30SDK_WIFI_GPIO_POWER_N,//RK30_PIN0_PB5, //MUST set to pin num in targetsystem
.rst =EXYNOS4_GPC1(1),//RK30SDK_WIFI_GPIO_RESET_N,//RK30_PIN3_PD0, //MUST set to pinnum in target system
.bgf_int=EXYNOS4_GPX2(4),//IRQ_EINT(20),//RK30SDK_WIFI_GPIO_BGF_INT_B,//RK30_PIN0_PA5,//MUST set to pinnum in target system if use UART interface.
.urt_cts = -EINVAL, // set it to thecorrect GPIO num if use common SDIO, otherwise set it to -EINVAL.
.rtc = -EINVAL, //Optipnal. refer to HWdesign.
.gps_sync = -EINVAL, //Optional. referto HW design.
.gps_lna = -EINVAL, //Optional. referto HW design.
};
static struct mtk_sdio_eint_platform_datamtk_sdio_eint_pdata = {
.sdio_eint =EXYNOS4_GPX2(5),//IRQ_EINT(21) ,//RK30SDK_WIFI_GPIO_WIFI_INT_B,//53, //MUST setpin num in target system.
};
static struct platform_device mtk_wmt_dev ={
.name = "mtk_wmt",
.id = 1,
.dev = {
.platform_data = &mtk_wmt_pdata,
},
};
static struct platform_devicemtk_sdio_eint_dev = {
.name = "mtk_sdio_eint",
.id = 1,
.dev = {
.platform_data =&mtk_sdio_eint_pdata,
},
};
2 WIFI驱动导出函数.
文件:
kernel/iTop4412_Kernel_3.0/drivers/misc/mediatek/combo_mt66xx/wmt/platform/vendor/wmt_plat.c
修改函数: wmt_plat_sdio_ctrl
函数说明: 该函数会调用我们上面导出的接口,让MMC总线控制器扫描新设备
INT32 wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_NUM sdioPortType, ENUM_FUNC_STATE on)
{
int ret = 0;
extern voidsetup_mt6620_wlan_power_for_onoff(int on);
if (FUNC_OFF == on) {
/* add control logic here to generateSDIO CARD REMOVAL event to mmc/sd
* controller. SDIO card removaloperation and remove success messages
* are expected.
*/
//add by dg 2015-04-14
setup_mt6620_wlan_power_for_onoff(0);
}
else {
/* add control logic here to generateSDIO CARD INSERTION event to mmc/sd
* controller. SDIO card detectionoperation and detect success messages
* are expected.
*/
//add by dg 2015-04-14
setup_mt6620_wlan_power_for_onoff(1);
}
//extern intomap_mmc_update_mtk_card_status(int state);
//ret =omap_mmc_update_mtk_card_status((FUNC_OFF == on)? 0: 1);
WMT_INFO_FUNC(KERN_INFO "%s, on=%d,ret=%d\n", __FUNCTION__, on, ret);
return ret;
}
以上两个文件的修改最为关键,当然您还需要配置MMC3的相关引脚为MMC工作状态,默认情况下面MMC3相关引脚为复用引脚中的GPIO状态,我们需要配置为MMC总线状态,笔者在调试过程中总是发现MMC总线上面没有命令或者数据输出,后发现默认情况下MMC3相关引脚并没有配置成MMC工作模式,查看Exynos4412 Datasheet后才发现这一问题.修改工作模式后,此问题得到解决.
MTK 官方给的移植文档中会告诉你需要在原始内核代码里面增加哪些文件,如何在make menuconfig中配置相关部分,这里就不再详细描述..