开发环境:win10 64位 + VMware12 + Ubuntu14.04 32位

工具链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabi

要移植的kernel版本:linux-4.4

Tiny4412开发板硬件版本为

  底板:  Tiny4412SDK 1312B

  核心板:Tiny4412 - 1306

——————————————————————————————————————————————————————————

 1,查看原理图

 

与整个DM9621相连的有三个口,DP1+和DM1-与USB4640连接传输数据。另有一个复位口,控制网卡使能,低电平有效。所以我们在配置设备树USB-HUB时, 需要将GPM2_4拉低。

 

2,Patch

diff --git a/include/linux/platform_data/usb4640.h b/include/linux/platform_data/usb4640.h
new file mode 100644
index 0000000..062a50c
--- /dev/null
+++ b/include/linux/platform_data/usb4640.h
@@ -0,0 +1,24 @@
+#ifndef __USB4640_H__
+#define __USB4640_H__
+
+#define USB4640_NAME   "usb4640"

+enum usb4640_mode {
+       USB4640_MODE_UNKNOWN = 1,
+       USB4640_MODE_HUB,
+       USB4640_MODE_STANDBY,
+};
+
+struct usb4640_platform_data {
+       enum usb4640_mode       initial_mode;
+#define USB4640_NAME   "usb4640"

+enum usb4640_mode {
+       USB4640_MODE_UNKNOWN = 1,
+       USB4640_MODE_HUB,
+       USB4640_MODE_STANDBY,
+};
+
+struct usb4640_platform_data {
+       enum usb4640_mode       initial_mode;
+     int     gpio_reset;
+};
+
+#endif
diff --git a/include/dt-bindings/usb4640/usb4640.h b/include/dt-bindings/usb4640/usb4640.h
new file mode 100644
index 0000000..ef3e1e1
--- /dev/null
+++ b/include/dt-bindings/usb4640/usb4640.h
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_USB4640
+#define _DT_BINDINGS_USB4640
+
+#define USB4640_MODE_UNKNOWN   1
+#define USB4640_MODE_HUB       2
+#define USB4640_MODE_STANDBY   3
+#endif
diff --git a/drivers/usb/misc/usb4640.c b/drivers/usb/misc/usb4640.c
new file mode 100644
index 0000000..b7bc085
--- /dev/null
+++ b/drivers/usb/misc/usb4640.c
@@ -0,0 +1,157 @@
+/*
+ * Driver for SMSC USB4640 USB 2.0 hub controller driver
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb4640.h>
+
+struct usb4640 {
+       enum usb4640_mode       mode;
+       struct device           *dev;
+       int     gpio_reset;
+};
+
+static int usb4640_reset(struct usb4640 *hub, int state)
+{
+       if (gpio_is_valid(hub->gpio_reset))
+               gpio_set_value_cansleep(hub->gpio_reset, state);
+
+       /* Wait 1ms for hub logic to stabilize */
+       if (state)
+               usleep_range(1, 10);
+
+       return 0;
+}
+
+static int usb4640_connect(struct usb4640 *hub)
+{
+       struct device *dev = hub->dev;
+
+       usb4640_reset(hub, 1);
+       hub->mode = USB4640_MODE_HUB;
+       dev_info(dev, "switched to HUB mode\n");
+
+       return 0;
+}
+
+static int usb4640_switch_mode(struct usb4640 *hub, enum usb4640_mode mode)
+{
+       struct device *dev = hub->dev;
+       int err = 0;
+
+       switch (mode) {
+       case USB4640_MODE_HUB:
+               err = usb4640_connect(hub);
+               break;
+
+       case USB4640_MODE_STANDBY:
+               usb4640_reset(hub, 0);
+               dev_info(dev, "switched to STANDBY mode\n");
+               break;
+
+       default:
+               dev_err(dev, "unknown mode is requested\n");
+               err = -EINVAL;
+               break;
+       }
+
+       return err;
+}
+
+
+static int usb4640_probe(struct usb4640 *hub)
+{
+       struct device *dev = hub->dev;
+       struct usb4640_platform_data *pdata = dev_get_platdata(dev);
+       struct device_node *np = dev->of_node;
+       int err;
+       u32 mode = USB4640_MODE_HUB;
+
+       if (pdata) {
+               hub->gpio_reset         = pdata->gpio_reset;
+               hub->mode               = pdata->initial_mode;
+       } else if (np) {
+               hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0);
+               if (hub->gpio_reset == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               of_property_read_u32(np, "initial-mode", &mode);
+               hub->mode = mode;
+       }
+
+       if (gpio_is_valid(hub->gpio_reset)) {
+               err = devm_gpio_request_one(dev, hub->gpio_reset,
+                               GPIOF_OUT_INIT_LOW, "usb4640 reset");
+               if (err) {
+                       dev_err(dev,
+                               "unable to request GPIO %d as reset pin (%d)\n",
+                               hub->gpio_reset, err);
+                       return err;
+               }
+       } else
+               dev_err(dev, "reset gpio is invalid: %d\n", hub->gpio_reset);
+
+       usb4640_switch_mode(hub, hub->mode);
+
+       dev_info(dev, "%s: probed in %s mode\n", __func__,
+                       (hub->mode == USB4640_MODE_HUB) ? "hub" : "standby");
+
+       return 0;
+}
+
+static int usb4640_platform_probe(struct platform_device *pdev)
+{
+       struct usb4640 *hub;
+
+       hub = devm_kzalloc(&pdev->dev, sizeof(struct usb4640), GFP_KERNEL);
+       if (!hub)
+               return -ENOMEM;
+       hub->dev = &pdev->dev;
+
+       return usb4640_probe(hub);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id usb4640_of_match[] = {
+       { .compatible = "smsc,usb4640", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, usb4640_of_match);
+#endif
+
+static struct platform_driver usb4640_platform_driver = {
+       .driver = {
+               .name = USB4640_NAME,
+#ifdef CONFIG_OF
+               .of_match_table = of_match_ptr(usb4640_of_match),
+#endif
+       },
+       .probe          = usb4640_platform_probe,
+};
+
+static int __init usb4640_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&usb4640_platform_driver);
+       if (err != 0)
+               pr_err("usb4640: Failed to register platform driver: %d\n",
+                      err);
+
+       return 0;
+}
+module_init(usb4640_init);
+
+static void __exit usb4640_exit(void)
+{
+       platform_driver_unregister(&usb4640_platform_driver);
+}
+module_exit(usb4640_exit);
+
+MODULE_DESCRIPTION("USB4640 USB HUB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 45fd4ac..98f81ed 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -25,6 +25,9 @@ obj-$(CONFIG_USB_USS720)              += uss720.o
 obj-$(CONFIG_USB_SEVSEG)               += usbsevseg.o
 obj-$(CONFIG_USB_YUREX)                        += yurex.o
 obj-$(CONFIG_USB_HSIC_USB3503)         += usb3503.o
+
+obj-$(CONFIG_USB_HSIC_USB4640)         += usb4640.o
+
 obj-$(CONFIG_USB_CHAOSKEY)             += chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)            += sisusbvga/
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index f7a7fc2..9692ca5 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -249,6 +249,11 @@ config USB_HSIC_USB3503
        help
          This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
 
+config USB_HSIC_USB4640
+        tristate "USB4640 HSIC to USB20 Driver"
+        help
+            This option enables support for SMSC USB4640 HSIC to USB 2.0 Driver.
+
 config USB_LINK_LAYER_TEST
        tristate "USB Link Layer Test driver"
        help
diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos
index 048ae67..948f2d9 100644
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 #include "exynos4412.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/usb4640/usb4640.h>
 
 / {
        model = "FriendlyARM TINY4412 board based on Exynos4412";
@@ -21,13 +22,16 @@
 
        chosen {
                stdout-path = &serial_0;
-        bootargs="root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=
-       };
+     bootargs="root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 et hmac=1C:6F:65:34:51:7E init=/linuxrc ignore_loglevel earlyprink";
+ 
+    };
+
 
        memory {
+               device_type = "memory";
                reg = <0x40000000 0x40000000>;
        };
-
+    
        leds {
                compatible = "gpio-leds";
 
@@ -69,8 +73,17 @@
                        clock-frequency = <24000000>;
                };
        };
+
+    usb-hub {
+        compatible = "smsc,usb4640";
+        reset-gpios = <&gpm2 4 GPIO_ACTIVE_LOW>;
+        initial-mode = <USB4640_MODE_HUB>; 
+        status = "okay";
+    };
 };
 
+
+
 &rtc {
        status = "okay";
 };
@@ -98,3 +111,47 @@
 &serial_3 {
        status = "okay";
 };
+
+&mshc_0 {
+   pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+   pinctrl-names = "default";
+   status = "okay";
+     
+   num-slots = <1>;
+   broken-cd;
+   card-detect-delay = <200>;
+   samsung,dw-mshc-ciu-div = <3>;
+   samsung,dw-mshc-sdr-timing = <2 3>;
+   samsung,dw-mshc-ddr-timing = <1 2>;
+   bus-width = <8>;
+   cap-mmc-highspeed;
+};
+
+
+&exynos_usbphy {
+    status = "okay";
+};
+
+&ehci {
+    status = "okay";
+    port@0 {
+        status = "okay";
+    };
+    port@1 {
+        status = "okay";
+    };
+    port@2 {
+        status = "okay";
+    };
+};
+
+&ohci {
+    status = "okay";
+    port@0 {
+        status = "okay";
+     };
+};
+
+&hsotg {
+    status = "okay";
+};
+

 

diff --git a/tiny4412_defconfig b/tiny4412_defconfig
index 91cba5b..178cea8 100644
--- a/tiny4412_defconfig
+++ b/tiny4412_defconfig
@@ -1160,7 +1160,7 @@ CONFIG_USB_NET_CDCETHER=y
 CONFIG_USB_NET_CDC_NCM=y
 # CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
 # CONFIG_USB_NET_CDC_MBIM is not set
-# CONFIG_USB_NET_DM9601 is not set
+CONFIG_USB_NET_DM9601=y
 # CONFIG_USB_NET_SR9700 is not set
 # CONFIG_USB_NET_SR9800 is not set
 CONFIG_USB_NET_SMSC75XX=y
@@ -2628,7 +2628,8 @@ CONFIG_USB_DWC2_DUAL_ROLE=y
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_YUREX is not set
 # CONFIG_USB_EZUSB_FX2 is not set
-CONFIG_USB_HSIC_USB3503=y
+# CONFIG_USB_HSIC_USB3503 is not set
+CONFIG_USB_HSIC_USB4640=y
 # CONFIG_USB_LINK_LAYER_TEST is not set
 # CONFIG_USB_CHAOSKEY is not set

 

 结果:

 

 

发现缺少IP地址

[root@tiny4412:/]#ifconfig eth0 192.168.1.130

完成。

posted on 2019-04-25 15:26  ._初一  阅读(736)  评论(0编辑  收藏  举报