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


开发板: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!!\n");
	}else{
		gpio_direction_input(ENC28J60_INTERRUPT_GPIO);
		
		//printk("enc28j60 gpio %d irq %d\n", ENC28J60_INTERRUPT_GPIO, irq);
		irq = gpio_to_irq(ENC28J60_INTERRUPT_GPIO);
		if(irq < 0){
			printk(KERN_ERR"claim gpio irq error!!\n");
		}else{
			printk("enc28j60 gpio %d irq %d\n", 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通了,至此大功告成。


你可能感兴趣的:(Linux驱动移植——ENC28J60以太网控制器)