zoukankan      html  css  js  c++  java
  • linux enc28j60网卡驱动移植(硬件spi和模拟spi)

    本来想移植DM9000网卡的驱动,无奈硬件出了点问题,通过杜邦线链接开发板和DM9000网卡模块,系统上电,还没加载网卡驱动就直接崩溃了,找不到原因。。。刚好手上有一个enc28j60的网卡模块,于是就着手移植enc28j60的驱动。

    其实移植enc28j60的驱动也十分简单,网上有现成的,只需要分配一些硬件资源即可。

    由于我的内核版本老到掉牙,没有自带enc28j60的驱动,只能在网上找一个:

    enc28j60.c

    http://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/7dac6f8df607929e51f4fd598d80bd009c45a9f8/drivers/net/enc28j60.c

    enc28j60_hw.h

    http://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/7dac6f8df607929e51f4fd598d80bd009c45a9f8/drivers/net/enc28j60_hw.h

    由于这个驱动是支持较新的内核,移植到2.6.22.6,只要改动3个地方好了。

     1 ... ...
     2 
     3 static int enc28j60_set_hw_macaddr(struct net_device *ndev)
     4 {
     5     ... ...
     6     
     7     if (!priv->hw_enable) {
     8         if (netif_msg_drv(priv)) {
     9             /* [cgw]: 屏蔽一下几行 */
    10             //DECLARE_MAC_BUF(mac);
    11             //printk(KERN_INFO DRV_NAME
    12             //    ": %s: Setting MAC address to %s
    ",
    13             //    ndev->name, print_mac(mac, ndev->dev_addr));
    14         }
    15     }
    16 
    17     ... ...
    18 }
    19 
    20 ... ...
    21 
    22 static void dump_packet(const char *msg, int len, const char *data)
    23 {
    24     printk(KERN_DEBUG DRV_NAME ": %s - packet len:%d
    ", msg, len);
    25     /* [cgw]: 屏蔽一下几行 */
    26     //print_hex_dump(KERN_DEBUG, "pk data: ", DUMP_PREFIX_OFFSET, 16, 1,
    27     //        data, len, true);
    28 }
    29 
    30 ... ...
    31     
    32 static int enc28j60_net_open(struct net_device *dev)
    33 {
    34     ... ...
    35 
    36     if (!is_valid_ether_addr(dev->dev_addr)) {
    37         if (netif_msg_ifup(priv)) {
    38             /* [cgw]: 屏蔽一下几行 */
    39             //DECLARE_MAC_BUF(mac);
    40             //dev_err(&dev->dev, "invalid MAC address %s
    ",
    41             //    print_mac(mac, dev->dev_addr));
    42         }
    43         return -EADDRNOTAVAIL;
    44     }
    45 
    46     ... ...
    47 }
    48 
    49 ... ...


    都是些打印相关的东西,屏蔽掉就好。

    spi的框架可以参考这里:http://www.cnblogs.com/hackfun/p/6082489.html

    这里只列出配置spi硬件资源的代码,只需要写一个spi_platform_dev.c文件就行了。模拟spi的模式下,spi_platform_dev.c和http://www.cnblogs.com/hackfun/p/6082489.html这里的spi_platform_dev.c文件相似,只需要增加一个外部中断入口给enc28j60用于接收中断,和更改spi的模式等。

    模拟spi的模式下的spi_platform_dev.c

      1 #include <linux/module.h>
      2 #include <linux/version.h>
      3 
      4 #include <linux/init.h>
      5 
      6 #include <linux/kernel.h>
      7 #include <linux/types.h>
      8 #include <linux/interrupt.h>
      9 #include <linux/list.h>
     10 #include <linux/timer.h>
     11 #include <linux/init.h>
     12 #include <linux/serial_core.h>
     13 #include <linux/platform_device.h>
     14 #include <linux/irq.h>
     15 
     16 #include <asm/gpio.h>
     17 #include <asm/io.h>
     18 #include <asm/arch/regs-gpio.h>
     19 
     20 #include <linux/spi/spi.h>
     21 #include <linux/spi/spi_bitbang.h>
     22 
     23 #include <asm/arch/regs-spi.h>
     24 #include <asm/arch/spi.h>
     25 #include <asm/arch/spi-gpio.h>
     26 
     27 
     28 static struct spi_board_info board_info[1] = {
     29     {
     30     .modalias = "enc28j60",    /* [cgw]: spi设备名,和设备驱动名对应 */
     31     .bus_num = 0,                 /* [cgw]: spi总线号,即spi0 */
     32     .chip_select = 2,             /* [cgw]: spi总线上的设备号,即spi0.2 */
     33     .max_speed_hz    = 50000,     /* [cgw]: spi时钟 */
     34     .mode = SPI_MODE_0,           /* [cgw]: spi数据模式 */
     35     .irq = IRQ_EINT2,
     36     },
     37 };
     38 
     39 
     40 static void enc28j60_chip_select(struct s3c2410_spigpio_info *spi, int cs)
     41 {
     42     /* [cgw]: 选中设备号为2的spi设备 */
     43     if (spi->board_info->chip_select == 2) {
     44         s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPIO_OUTPUT);
     45         /* [cgw]: 选中设备 */
     46         if (BITBANG_CS_ACTIVE == cs) {
     47             s3c2410_gpio_setpin(S3C2410_GPG2, 0);
     48         /* [cgw]: 释放设备 */
     49         } else if (BITBANG_CS_INACTIVE == cs) {
     50             s3c2410_gpio_setpin(S3C2410_GPG2, 1);
     51         }
     52     }
     53 }
     54 
     55 /* [cgw]:  */
     56 static struct s3c2410_spigpio_info spi_dev = {
     57     .pin_clk = S3C2410_GPG7,
     58     .pin_mosi = S3C2410_GPG6,
     59     .pin_miso = S3C2410_GPG5,
     60     .board_size = 1,                    /* [cgw]: 设置板上spi接口数量为1 */
     61     .board_info = &board_info[0],
     62     .chip_select = enc28j60_chip_select
     63 };
     64 
     65 static void spi_dev_release(struct device * dev)
     66 {
     67     printk("spi_dev_release! 
    ");
     68 }
     69 
     70 /* [cgw]: 分配一个平台设备 */
     71 static struct platform_device spi_platform_dev = {
     72     .name         = "s3c24xx-spi-gpio",        /* [cgw]: 设置平台设备名,和平台驱动名对应 */
     73     .id           = -1,
     74     .dev = { 
     75         .release = spi_dev_release,
     76         .platform_data = (void *)&spi_dev,      /* [cgw]: 通过platform_data传递spi_dev给平台驱动
     77                                                 * 平台驱动可以访问spi_dev
     78                                                 */
     79     },
     80 };
     81 
     82 
     83 static int spi_dev_init(void)
     84 {
     85     s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
     86 
     87     /* [cgw]: 注册spi_platform_dev平台设备 */
     88     platform_device_register(&spi_platform_dev);
     89     return 0;
     90 }
     91 
     92 static void spi_dev_exit(void)
     93 {
     94     /* [cgw]: 注销spi_platform_dev平台设备 */
     95     platform_device_unregister(&spi_platform_dev);
     96 }
     97 
     98 module_init(spi_dev_init);
     99 module_exit(spi_dev_exit);
    100 
    101 MODULE_LICENSE("GPL");

    makefile:

    KERN_DIR = /work/system/linux-2.6.22.6
    
    all:
        make -C $(KERN_DIR) M=`pwd` modules 
    
    clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
    
    obj-m    += spi_platform_dev.o
    obj-m    += spi_s3c24xx_gpio.o
    obj-m    += spi_bitbang.o
    obj-m    += enc28j60.o

    硬件spi的模式下的spi_platform_dev.c

      1 #include <linux/module.h>
      2 #include <linux/version.h>
      3 
      4 #include <linux/init.h>
      5 
      6 #include <linux/kernel.h>
      7 #include <linux/types.h>
      8 #include <linux/interrupt.h>
      9 #include <linux/list.h>
     10 #include <linux/timer.h>
     11 #include <linux/init.h>
     12 #include <linux/serial_core.h>
     13 #include <linux/platform_device.h>
     14 #include <linux/irq.h>
     15 
     16 #include <asm/gpio.h>
     17 #include <asm/io.h>
     18 #include <asm/arch/regs-gpio.h>
     19 
     20 #include <linux/spi/spi.h>
     21 #include <linux/spi/spi_bitbang.h>
     22 
     23 #include <asm/arch/regs-spi.h>
     24 #include <asm/arch/spi.h>
     25 #include <asm/arch/spi-gpio.h>
     26 
     27 
     28 /* SPI (1) */
     29 
     30 static struct resource s3c_spi1_resource[] = {
     31     [0] = {
     32         .start = S3C2410_PA_SPI + S3C2410_SPI1,
     33         .end   = S3C2410_PA_SPI + S3C2410_SPI1 + 0x1f,
     34         .flags = IORESOURCE_MEM,
     35     },
     36     [1] = {
     37         .start = IRQ_SPI1,
     38         .end   = IRQ_SPI1,
     39         .flags = IORESOURCE_IRQ,
     40     }
     41 
     42 };
     43 
     44 
     45 static struct spi_board_info board_info[1] = {
     46     {
     47     .modalias = "enc28j60",    /* [cgw]: spi设备名,和设备驱动名对应 */
     48     .bus_num = 0,                 /* [cgw]: spi总线号,即spi0 */
     49     .chip_select = 2,             /* [cgw]: spi总线上的设备号,即spi0.2 */
     50     .max_speed_hz    = 50000,     /* [cgw]: spi时钟 */
     51     .mode = SPI_MODE_0,           /* [cgw]: spi数据模式 */
     52     .irq = IRQ_EINT2,
     53     },
     54 };
     55 
     56 static struct s3c2410_spi_info spi_info = {
     57     .pin_cs = S3C2410_GPG2,    /* simple gpio cs */
     58     .board_size = ARRAY_SIZE(board_info),
     59     .board_info = &board_info[0],
     60     .set_cs = NULL
     61 };
     62 
     63 
     64 static void spi_dev_release(struct device * dev)
     65 {
     66     printk("spi_dev_release! 
    ");
     67 }
     68 
     69 /* [cgw]: 分配一个平台设备 */
     70 static struct platform_device spi_platform_dev = {
     71     .name         = "s3c2410-spi",        /* [cgw]: 设置平台设备名,和平台驱动名对应 */
     72     .id           = 1,
     73     .num_resources      = ARRAY_SIZE(s3c_spi1_resource),
     74     .resource      = s3c_spi1_resource,
     75     .dev = { 
     76         .release = spi_dev_release,
     77         .platform_data = &spi_info,
     78         //.dma_mask = &s3c_device_spi1_dmamask,
     79         //.coherent_dma_mask = 0xffffffffUL
     80     },
     81 };
     82 
     83 
     84 static int spi_dev_init(void)
     85 {
     86     /* [cgw]: 注册spi_platform_dev平台设备 */
     87     platform_device_register(&spi_platform_dev);
     88     return 0;
     89 }
     90 
     91 static void spi_dev_exit(void)
     92 {
     93     /* [cgw]: 注销spi_platform_dev平台设备 */
     94     platform_device_unregister(&spi_platform_dev);
     95 }
     96 
     97 module_init(spi_dev_init);
     98 module_exit(spi_dev_exit);
     99 
    100 MODULE_LICENSE("GPL");

    makefile:

    KERN_DIR = /work/system/linux-2.6.22.6
    
    all:
        make -C $(KERN_DIR) M=`pwd` modules 
    
    clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
    
    obj-m    += spi_platform_dev.o
    obj-m    += spi_s3c24xx.o
    obj-m    += spi_bitbang.o
    obj-m    += enc28j60.o


    加载spi平台设备时(platform_device),应注意模拟spi时应加载spi_s3c24xx_gpio.c,硬件spi时应加载spi_s3c24xx.c

    如:

    模拟spi:

    1 # insmod spi_bitbang.ko
    2 # insmod spi_platform_dev.ko
    3 # insmod spi_s3c24xx_gpio.ko
    4 # insmod enc28j60.ko


    硬件spi:

    1 # insmod spi_bitbang.ko
    2 # insmod spi_platform_dev.ko
    3 # insmod spi_s3c24xx.ko
    4 # insmod enc28j60.ko


    其中spi_bitbang.c , spi_s3c24xx_gpio.c , spi_s3c24xx.c为内核原生源文件,不需要改动。

    硬件spi时,加载驱动的实例:

    谢谢!

  • 相关阅读:
    wget(转)
    852. Peak Index in a Mountain Array
    617. Merge Two Binary Trees
    814. Binary Tree Pruning
    657. Judge Route Circle
    861. Score After Flipping Matrix
    832. Flipping an Image
    461. Hamming Distance
    654. Maximum Binary Tree
    804. Unique Morse Code Words
  • 原文地址:https://www.cnblogs.com/hackfun/p/6260396.html
Copyright © 2011-2022 走看看