Linux驱动移植——ENC28J60以太网控制器

2019-07-13 02:41发布


开发板:E9(飞思卡尔的imx6q主控) 内核:Linux 3.0.35 PC OS:Ubuntu 11.04
本文对ENC28J60模块的驱动移植进行简单梳理。该模块购于淘宝。 按照一般移植要素,有如下几个步骤: 1. 按照各引脚所对应的功能进行初始化操作。
2. 确定总线类型,在bsp中注册相应的主控制器信息。 3.在bsp中添加设备信息。 4. 配置内核,打开设备配置选项。

1. 硬件连线方式

    IMX6开发板                        ENC28J60
CSPI2_CLK        --->               SCK
CSPI2_MISO      <---                 SO
CSPI2_MOSI      --->                  SI
CSPI_CS0          --->                 CS EIM_D21            <---                  INT VCC  3.3v             --->                VCC GND                     -->                 GND


2. 初始化引脚

从硬件连线方式可以看出,SPI总线使用的是imx6的SPI2控制器,同时额外需要一个GPIO作为中断引脚。
在原文件arch/arm/mach-mx6/board-mx6q_sabresd.h的数组mx6q_sabresd_pads数组中添加如下内容: /* ECSPI2*/ MX6Q_PAD_EIM_CS0__ECSPI2_SCLK, MX6Q_PAD_EIM_CS1__ECSPI2_MOSI, MX6Q_PAD_EIM_OE__ECSPI2_MISO, MX6Q_PAD_CSI0_DAT11__GPIO_5_29, //MX6Q_PAD_EIM_D17__GPIO_3_17, MX6Q_PAD_EIM_D21__GPIO_3_21, /* gpio interrupt for enc2860j */

3. 注册SPI控制器和SPI板级设备

由于ENC28J60使用SPI总线,因此,在注册板级设备设备前,需要弄SPI的一些参数。 ENC28J60使用SPI模式0进行传输,最大速率为10Mbps。 在原文件arch/arm/mach-mx6/board-mx6q_sabresd.c中添加如下结构体的声明: /* Following is added by Jone Yim for enc28j60 */ #define SABRESD_ECSPI2_CS0      IMX_GPIO_NR(5, 29)    /* CSPI2_CS0 */ #define ENC28J60_INTERRUPT_GPIO IMX_GPIO_NR(3, 21)    /* EIM_D21 */ static int mx6q_sabresd_spi2_cs[] = { SABRESD_ECSPI2_CS0, }; static const struct spi_imx_master mx6q_sabresd_spi2_data __initconst = { .chipselect = mx6q_sabresd_spi2_cs, .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi2_cs), }; static struct spi_board_info mx6_sabresd_spi2_board[]={    [0] = {              .modalias = "enc28j60",              .bus_num = 1,              .chip_select = 0,              .max_speed_hz = 5000 * 1000,              .mode = SPI_MODE_0,     }, };
首先通过宏定义了CS和INT所使用的引脚号,并定义了SPI板级设备。 接下来我们需要注册该SPI板级设备信息到内核中。 在同一文件下的mx6_sabresd_board_init函数中添加如下代码: /* Following is added by Jone Yim for enc28j60 */ imx6q_add_ecspi(1, &mx6q_sabresd_spi2_data); /*using ecspi2*/ ret = gpio_request(ENC28J60_INTERRUPT_GPIO, "ENC28J60-int"); if (ret) { printk(KERN_ERR"request ENC28J60-int error!! "); }else{ gpio_direction_input(ENC28J60_INTERRUPT_GPIO); //printk("enc28j60 gpio %d irq %d ", ENC28J60_INTERRUPT_GPIO, irq); irq = gpio_to_irq(ENC28J60_INTERRUPT_GPIO); if(irq < 0){ printk(KERN_ERR"claim gpio irq error!! "); }else{ printk("enc28j60 gpio %d irq %d ", ENC28J60_INTERRUPT_GPIO, irq); mx6_sabresd_spi2_board[0].irq = irq; irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); spi_register_board_info(mx6_sabresd_spi2_board, ARRAY_SIZE(mx6_sabresd_spi2_board)); } }首先注册SPI2控制器,然后在调用spi_register_board_info注册SPI板级设备信息之前,我们向系统申请了用于中断的GPIO引脚,并获取了其irq号,并将该irq号保存到SPI板级设备信息。 其次,我们需要设置GPIO的中断类型为下降沿中断,这跟datasheet里面描述的一致。这里提一句为什么要在这里设置中断类型,这是因为在ENC28J60驱动源码的probe方法中并未设置其中断类型,反而是有一段注释要求在bsp中设置中断类型。 一切就绪,最后spi_register_board_info调用注册SPI板级设备信息。

4.配置内核


配置完以后即可编译。

5.验证

系统启动后执行如下命令: ifconfig eth0 down   //关闭原有的网口
ifconfig eth1 up 192.168.0.116   //打开ENC28J60对应的网口并设置IP地址
然后ping以下虚拟机试试:
ping通了,至此大功告成。