基于tiny4412的Linux内核移植 -- DM9621NP网卡驱动移植(四)

2023-06-20  

平台简介

开发板:tiny4412ADK + S700 + 4GB Flash

要移植的内核版本:Linux-4.4.0 (支持device tree)

u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动)

busybox版本:busybox 1.25

网卡芯片:DM9621NP

交叉编译工具链: arm-none-linux-gnueabi-gcc

      (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29))


概述

tiny4412的网卡部分跟我之前的tq2440差别很大,在tq2440中使用网卡芯片是DM9000,使用的是内存接口,移植起来很容易,但是到了tiny4412就不一样了,tiny4412使用的网卡芯片是DM9621,它是usb接口的,而且并没有直接连接到exynos4412上,中间通过一个hub芯片usb4640,然后usb4640通过HSIC接口(XhsicSTROBE0和XhsicDATA0)连接到exynos4412上,下面是一些参考资料:

  • HSI介绍

         http://www.cnblogs.com/pengdonglin137/p/5151331.html

         http://www.cnblogs.com/pengdonglin137/p/5151006.html

  • exynos4412手册的第31章USB 2.0 Host Controller

image

 

image

 

  • 原理图

image

上面这张图就是tiny4412板子上的USB连接图,我们重点关注DM9621和USB4640。


移植

通过阅读usb4640的芯片手册,同时结合tiny4412的原理图发现,usb4640的部分功能在tiny4412上是没有用的,没有外接的SPI Flash和I2C设备,大部分引脚都悬空了,除了数据传输的端口外,我们可以控制的就只剩下USB4640的复位引脚了,并且板子起来后,我用万用表测量了usb4640的复位引脚的电压,发现是0.7v左右,说明usb4640一直处于复位状态,最终针对usb4640我们要做的就是只是板子起来后,将控制usb4640复位的引脚电平拉高即可,当然需要在设备树中添加usb4640用到的GPIO资源,usb4640的驱动文件我参考的是drivers/usb/misc/usb3503.c,只保留了关于控制gpio的代码。


通过对比tiny4412自带的linux-3.0.86版本的内核,对于DM9621的驱动在Linux 4.4中全部在driver/net/usb/dm9601.c中实现了,并且对于dm9601这样的usb设备不需要出现在设备树中。所以针对dm9601我们要做的就是:在内核配置时将DM9601的驱动选中即可,同时发现,为了支持识别bootargs中的mac地址的功能,需要稍微修改dm9601.c,添加解析mac地址的功能,并且还需要将解析到的有效的mac地址设置到dm9621中,否则网络没法用(发现这个问题也废了一些时间)。修改内核配置,添加dm9621的驱动:

make menuconfig

    Device Drivers  --->

        Network device support  --->

            USB Network Adapters  --->

                Davicom DM96xx based USB 10/100 ethernet devices

    此外,最关键的是一定要在设备树中将用到的片内外设使能:如hsi、ehci、ohci、otg等等。


    执行完这些操作后,板子上的三个usb口(USBH1/USBH2/USBH3)都可以识别了,即可以插入U盘等设备了。


下面是patch:


   1: diff --git a/Makefile b/Makefile

   2: index 70dea02..5d96411 100644

   3: --- a/Makefile

   4: +++ b/Makefile

   5: @@ -248,8 +248,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/

   6:  # "make" in the configured kernel build directory always uses that.

   7:  # Default value for CROSS_COMPILE is not to prefix executables

   8:  # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

   9: -ARCH        ?= $(SUBARCH)

  10: -CROSS_COMPILE    ?= $(CONFIG_CROSS_COMPILE:"%"=%)

  11: +ARCH        ?= arm

  12: +CROSS_COMPILE    ?= /root/tiny4412_android5/SysPort/cross_compile/arm-2014.05/bin/arm-none-linux-gnueabi-

  13:  

  14:  # Architecture as present in compile.h

  15:  UTS_MACHINE     := $(ARCH)

  16: diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts

  17: index 4840bbd..69a0d5d 100644

  18: --- a/arch/arm/boot/dts/exynos4412-tiny4412.dts

  19: +++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts

  20: @@ -14,6 +14,7 @@

  21:  /dts-v1/;

  22:  #include "exynos4412.dtsi"

  23:  #include

  24: +#include

  25:  

  26:  / {

  27:      model = "FriendlyARM TINY4412 board based on Exynos4412";

  28: @@ -21,6 +22,7 @@

  29:  

  30:      chosen {

  31:          stdout-path = &;serial_0;

  32: +        bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 ethmac=1C:6F:65:34:51:7E init=/linuxrc";

  33:      };

  34:  

  35:      memory {

  36: @@ -68,6 +70,12 @@

  37:              clock-frequency = ;

  38:          };

  39:      };

  40: +

  41: +    usb-hub {

  42: +        compatible = "smsc,usb4640";

  43: +        reset-gpios = ;

  44: +        initial-mode = ;

  45: +    };

  46:  };

  47:  

  48:  &;rtc {

  49: @@ -78,7 +86,7 @@

  50:      bus-width = ;

  51:      pinctrl-0 = ;

  52:      pinctrl-names = "default";

  53: -    status = "okay";

  54: +    status = "disabled";

  55:  };

  56:  

  57:  &;serial_0 {

  58: @@ -96,3 +104,32 @@

  59:  &;serial_3 {

  60:      status = "okay";

  61:  };

  62: +

  63: +&;exynos_usbphy {

  64: +    status = "okay";

  65: +};

  66: +

  67: +&;ehci {

  68: +    status = "okay";

  69: +    port@0 {

  70: +        status = "okay";

  71: +    };

  72: +    port@1 {

  73: +        status = "okay";

  74: +    };

  75: +    port@2 {

  76: +        status = "okay";

  77: +    };

  78: +};

  79: +

  80: +&;ohci {

  81: +    status = "okay";

  82: +    port@0 {

  83: +        status = "okay";

  84: +    };

  85: +};

  86: +

  87: +&;hsotg {

  88: +    status = "okay";

  89: +};

  90: +

  91: diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c

  92: index 0b4bdd3..4361385 100644

  93: --- a/drivers/net/usb/dm9601.c

  94: +++ b/drivers/net/usb/dm9601.c

  95: @@ -58,6 +58,39 @@

  96:  #define DM_RX_OVERHEAD    7    /* 3 byte header + 4 byte crc tail */

  97:  #define DM_TIMEOUT    1000

  98:  

  99: +/* Setup ethernet address */

 100: +static u8 param_addr[ETH_ALEN];

 101: +

 102: +static int __init dm9601_set_mac(char *str) {

 103: +    u8 addr[ETH_ALEN];

 104: +    uint val;

 105: +    int idx = 0;

 106: +    char *p = str, *end;

 107: +

 108: +    while (*p &;& idx < ETH_ALEN) {

 109: +        val = simple_strtoul(p, &;end, 16);

 110: +        if (end  111: +            break;

 112: +        } else {

 113: +            addr[idx++] = val;

 114: +            p = end;

 115: +            if (*p == ':'|| *p == '-') {

 116: +                p++;

 117: +            } else {

 118: +                break;

 119: +            }

 120: +        }

 121: +    }

 122: +

 123: +    if (idx == ETH_ALEN) {

 124: +        printk("Setup ethernet address to %pMn", addr);

 125: +        memcpy(param_addr, addr, ETH_ALEN);

 126: +    }

 127: +

 128: +    return 1;

 129: +}

 130: +__setup("ethmac=", dm9601_set_mac);

 131: +

 132:  static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)

 133:  {

 134:      int err;

 135: @@ -190,8 +223,6 @@ static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)

 136:      return dm_read_shared_word(dev, 0, offset, value);

 137:  }

 138:  

 139: -

 140: -

 141:  static int dm9601_get_eeprom_len(struct net_device *dev)

 142:  {

 143:      return DM_EEPROM_LEN;

 144: @@ -389,7 +420,11 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)

 145:      /*

 146:       * Overwrite the auto-generated address only with good ones.

 147:       */

 148: -    if (is_valid_ether_addr(mac))

 149: +    if (is_valid_ether_addr(param_addr)) {

 150: +        /* write MAC to dm9621 */

 151: +        memcpy(dev->;net->dev_addr, param_addr, ETH_ALEN);

 152: +        __dm9601_set_mac_address(dev);

 153: +    } else if (is_valid_ether_addr(mac))

 154:          memcpy(dev->;net->dev_addr, mac, ETH_ALEN);

 155:      else {

 156:          printk(KERN_WARNING

 157: diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig

 158: index f7a7fc2..c1fcc2f 100644

 159: --- a/drivers/usb/misc/Kconfig

 160: +++ b/drivers/usb/misc/Kconfig

 161: @@ -249,6 +249,11 @@ config USB_HSIC_USB3503

 162:         help

 163:           This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.

 164:  

 165: +config USB_HSIC_USB4640

 166: +       tristate "USB4640 HSIC to USB20 Driver"

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。