初识Linux Kernel 移植 之 dm9621网卡驱动移植
初识Linux 驱动移植 -- dm921概述配置内核dm9621 网卡驱动编译配置选项问题探索读 dm9621 MAC 地址失败网卡反复断开重连概述将kernel移植到开发板并能正常加载和启动内核后,发现网卡并没有工作,因此将网卡作为第一个移植的实践。这篇文章用于记录移植dm9621网卡过程中遇到的问题以及如何定位问题并尝试解决。配置内核在找到dm9621网卡驱动的源码后,需要将其添加到...
初识Linux 驱动移植 -- dm921
概述
将kernel移植到开发板并能正常加载和启动内核后,发现网卡并没有工作,因此将网卡作为第一个移植的实践。这篇文章用于记录移植dm9621网卡过程中遇到的问题以及如何定位问题并尝试解决。
配置内核
在找到dm9621网卡驱动的源码后,需要将其添加到内核,并编译到内核去不采用动态加载模块,需要做哪些修改呢?这需要通过内核配置菜单来配置,将dm9620.c(dm9621 网卡驱动源码)拷贝到 driver/net/usb 目录下,通过配置该目录下Kconfig 和 Makefile 来决定。
//Kconfig 添加(添加dm9620 编译选项):
+config USB_NET_DM9620
+ tristate "Davicom DM9620/21 based USB 2.0 10/100 ethernet devices"
+ depends on USB_USBNET
+ select CRC32
+ help
+ This option adds support for Davicom DM9620 based USB 2.0
+ 10/100 Ethernet adapters.
+
+ This driver creates an interface named "ethX",where X depends on
+ what other networking devices you have in use.
+
+ To compile this driver as a module.choose M here.
//Makefile 添加(CONFIG_USB_NET_DM9620 为 y时编译进内核,为 M 时编译成模块):
+ obj-$(CONFIG_USB_NET_DM9620) += dm9620.o
添加好之后就可以通过 make menuconfig来配置了,由于dm9621是usb类型网卡,因此需要依赖于usb 网络框架:
Device Drivers --->
[*] Network device support --->
USB Network Adapters --->
<*> Multi-purpose USB Networking Framework
<*> Davicom DM9620/21 based USB 2.0 10/100 ethernet devices
dm9621 网卡驱动编译配置选项
问题探索
读 dm9621 MAC 地址失败
在kernel的启动信息中可以看到dm9620 相关的启动信息中有这样一条信息:
(unregistered net_device): Error reading MAC address
这信息来源在 调用usbnet_probe()函数(usbnet.c)中调用bind函数时读取MAC地址失败,目标网卡设备未注册。通过添加调试来排查dm9620驱动注册是否成功,下面是dm9620驱动注册过程中函数调用关系:
usb_register() // module_init(usb_register)
usb_register_driver() // 注册一个 USB interface 驱动
driver_register() // 总线型驱动注册(dm9620 是usb类型)
bus_add_driver() // 将驱动添加到总线(将dm9620驱动添加到usb总线)
driver_attach() // 将驱动绑定到设备
bus_for_each_dev() // 设备迭代器,查找所有的设备,并调用回调函数
__driver_attach() // 绑定查找到的设备
driver_match_device() // 实现驱动和设备的匹配工作
driver_probe_device() // 如果匹配成功会调用该函数,将设备和驱动进行绑定
通过添加调试信息,在执行调用driver_match_device函数后会由于匹配dm9620驱动和设备失败返回,而不调用driver_probe_device函数进行设备和驱动的绑定。分析到这就猜测是不是设备的问题,通过使用lsusb命令,发现并没有dm9621 的usb网卡设备,因此推测应该是网卡设备没有被发现导致注册失败。而这个网卡设备是通过usb3503A hub连接到开发板的,在使用lsusb命令时同样没有发现3053 usb设备,因此呢这个usb设备也没有被发现。通过查看usb3503A 的初始化操作,发现原代码使用的GPIO引脚并非板子上usb3503 链接的引脚,因此需要修改usb3503A 的reset 和 connect 引脚:
// 位于板子配置初始化文件中 arch/arm/mach-exynos/mach-smdk4x12.c
// usb_hub_gpio_init() 对usb3503 引脚进行初始化
- #define GPIO_HUB_RESET EXYNOS4_GPL2(2)
- #define GPIO_HUB_CONNECT EXYNOS4_GPK3(2)
+ #define GPIO_HUB_RESET EXYNOS4212_GPM2(4)
+ #define GPIO_HUB_CONNECT EXYNOS4212_GPM3(3)
通过修改上面的修改,重新编译加载内核后,再次使用lsusb命令,可以查看到已经发现了usb3503 和 dm9621 设备:
网卡反复断开重连
通过之前的修改,虽然已经发现了网卡设备,但是发现网卡设备会发生2~3次的被发现和断开,下面是kernel中dm9620驱动相关的启动信息:
这是怎么回事呢?这种现象很像是多次插拔了usb网卡,通过开发板的原理图发现,dm9621 的RSTB引脚是链接到4412芯片的GPC0_1 引脚,猜测可能该引脚被多次的配置,因为将这个引脚拉低会初始化dm9621 ,因此会造成这种类似的现象。通过搜索,发现GPC0_1 在原码中被当成其他引脚功能使用,因此将这些使用了该引脚代码注释掉(在s3c-fb.c 和setup-fb-s5p.c中引用,原因是暂时还没找到这些原码应该使用哪个才是正确的引脚)。同时在板级初始化函数中添加对dm9621的初始化:
static void __init smdk4x12_machine_init(void)
{
……
+ #ifdef CONFIG_USB_NET_DM9620
+ dm9620_reset();
+ #endif
}
+ #ifdef CONFIG_USB_NET_DM9620
+ static void __init dm9620_reset(void)
+ {
+ int err = 0;
+ err = gpio_request_one(EXYNOS4_GPC0(1), GPIOF_OUT_INIT_HIGH, "DM9620_RESET");
+ if (err)
+ pr_err("failed to request GPC0_1 for DM9620 reset control\n");
+ s3c_gpio_setpull(EXYNOS4_GPC0(1), S3C_GPIO_PULL_UP);
+ gpio_set_value(EXYNOS4_GPC0(1), 0);
+ mdelay(1000); //dg change 5 ms to 1000ms for test dm9620
+ gpio_set_value(EXYNOS4_GPC0(1), 1);
+ gpio_free(EXYNOS4_GPC0(1));
+}
+ #endif
更多推荐
所有评论(0)