usb: add usb3.0 driver support for g12a
authorYue Wang <yue.wang@amlogic.com>
Fri, 2 Feb 2018 11:41:59 +0000 (19:41 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Fri, 2 Mar 2018 07:07:55 +0000 (15:07 +0800)
PD#156734: usb: add usb3.0 driver support for g12a

Change-Id: Iac057b29d041a5c80114407df0ccd965aae11ca1
Signed-off-by: Yue Wang <yue.wang@amlogic.com>
arch/arm64/boot/dts/amlogic/g12a_skt.dts
drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/host.c
drivers/usb/host/xhci-plat.c
include/linux/amlogic/usb-v2.h
include/linux/amlogic/usbtype.h

index 4ca6bca..9b956e3 100644 (file)
                clock-src = "usb3.0";
                clocks = <&clkc CLKID_USB_GENERAL>;
                clock-names = "dwc_general";
-               /*snps,super_speed_support;*/
        };
 
        usb2_phy_v2: usb2phy@ffe09000 {
                phy-reg-size = <0x4>;
                interrupts = <0 16 4>;
                otg = <0>;
+               clocks = <&clkc CLKID_PCIE_PLL>;
+               clock-names = "pcie_refpll";
        };
 
        dwc2_a {
index 316f7f6..25328c0 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/amlogic/aml_gpio_consumer.h>
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
+#include <linux/amlogic/usbtype.h>
 #include "phy-aml-new-usb-v2.h"
 
 #define HOST_MODE      0
@@ -131,17 +132,13 @@ static int amlogic_new_usb3_init(struct usb_phy *x)
                return 0;
        }
 
-       /* set the phy from pcie to usb3 */
-       if (phy->portnum > 0)
-               writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg);
-
        for (i = 0; i < 6; i++) {
                usb_new_aml_regs_v2.usb_r_v2[i] = (void __iomem *)
                        ((unsigned long)phy->regs + 4*i);
        }
 
        r1.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[1]);
-       r1.b.u3h_fladj_30mhz_reg = 0x20;
+       r1.b.u3h_fladj_30mhz_reg = 0x26;
        writel(r1.d32, usb_new_aml_regs_v2.usb_r_v2[1]);
 
        r5.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[5]);
@@ -164,7 +161,7 @@ static int amlogic_new_usb3_init(struct usb_phy *x)
                udelay(2);
                r1.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[1]);
                r1.b.u3h_host_port_power_control_present = 1;
-               r1.b.u3h_fladj_30mhz_reg = 32;
+               r1.b.u3h_fladj_30mhz_reg = 0x26;
                writel(r1.d32, usb_new_aml_regs_v2.usb_r_v2[1]);
                udelay(2);
        }
@@ -256,6 +253,26 @@ static irqreturn_t amlogic_botg_detect_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static bool device_is_available(const struct device_node *device)
+{
+       const char *status;
+       int statlen;
+
+       if (!device)
+               return false;
+
+       status = of_get_property(device, "status", &statlen);
+       if (status == NULL)
+               return true;
+
+       if (statlen > 0) {
+               if (!strcmp(status, "okay") || !strcmp(status, "ok"))
+                       return true;
+       }
+
+       return false;
+}
+
 static int amlogic_new_usb3_v2_probe(struct platform_device *pdev)
 {
        struct amlogic_usb_v2                   *phy;
@@ -273,6 +290,8 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev)
        int retval;
        int gpio_vbus_power_pin = -1;
        int otg = 0;
+       int ret;
+       struct device_node *tsi_pci;
 
        gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL);
        if (gpio_name) {
@@ -290,6 +309,15 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev)
        if (!portnum)
                dev_err(&pdev->dev, "This phy has no usb port\n");
 
+       tsi_pci = of_find_node_by_type(NULL, "pci");
+       if (tsi_pci) {
+               if (device_is_available(tsi_pci)) {
+                       dev_info(&pdev->dev,
+                               "pci-e driver probe, disable USB 3.0 function!!!\n");
+                       portnum = 0;
+               }
+       }
+
        prop = of_get_property(dev->of_node, "otg", NULL);
        if (prop)
                otg = of_read_ulong(prop, 1);
@@ -347,9 +375,31 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev)
        phy->phy.set_suspend    = amlogic_new_usb3_suspend;
        phy->phy.shutdown       = amlogic_new_usb3phy_shutdown;
        phy->phy.type           = USB_PHY_TYPE_USB3;
+       phy->phy.flags          = AML_USB3_PHY_DISABLE;
        phy->vbus_power_pin = gpio_vbus_power_pin;
        phy->usb_gpio_desc = usb_gd;
 
+       /* set the phy from pcie to usb3 */
+       if (phy->portnum > 0) {
+               writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg);
+               udelay(100);
+
+               phy->clk = devm_clk_get(dev, "pcie_refpll");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "Failed to get usb3 bus clock\n");
+                       ret = PTR_ERR(phy->clk);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(phy->clk);
+               if (ret) {
+                       dev_err(dev, "Failed to enable usb3 bus clock\n");
+                       ret = PTR_ERR(phy->clk);
+                       return ret;
+               }
+               phy->phy.flags = AML_USB3_PHY_ENABLE;
+       }
+
        INIT_DELAYED_WORK(&phy->work, amlogic_gxl_work);
 
        usb_add_phy_dev(&phy->phy);
index a2926a6..5a5ad4f 100644 (file)
@@ -212,6 +212,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
 
        usb_phy_init(dwc->usb2_phy);
        usb_phy_init(dwc->usb3_phy);
+
        ret = phy_init(dwc->usb2_generic_phy);
        if (ret < 0)
                return ret;
@@ -221,7 +222,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
                phy_exit(dwc->usb2_generic_phy);
                return ret;
        }
-       mdelay(100);
+
+       udelay(1000);
 
        /* Clear USB3 PHY reset */
        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
@@ -249,7 +251,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
        reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(3), reg);
 
-       mdelay(100);
+       udelay(1000);
 
        /* After PHYs are stable we can take Core out of reset state */
        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -925,6 +927,13 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
                }
        }
 
+#ifdef CONFIG_AMLOGIC_USB
+       if (dwc->usb3_phy->flags == AML_USB3_PHY_ENABLE)
+               dwc->super_speed_support = 1;
+       else
+               dwc->super_speed_support = 0;
+#endif
+
        dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
        if (IS_ERR(dwc->usb2_generic_phy)) {
                ret = PTR_ERR(dwc->usb2_generic_phy);
@@ -1141,10 +1150,7 @@ static int dwc3_probe(struct platform_device *pdev)
                                    &dwc->hsphy_interface);
        device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
                                 &dwc->fladj);
-#ifdef CONFIG_AMLOGIC_USB
-       dwc->super_speed_support = device_property_read_bool(dev,
-                               "snps,super_speed_support");
-#endif
+
        dwc->lpm_nyet_threshold = lpm_nyet_threshold;
        dwc->tx_de_emphasis = tx_de_emphasis;
 
index 2ea098c..fe075ac 100644 (file)
@@ -105,6 +105,11 @@ int dwc3_host_init(struct dwc3 *dwc)
        if (dwc->revision <= DWC3_REVISION_300A)
                props[prop_idx++].name = "quirk-broken-port-ped";
 
+#ifdef CONFIG_AMLOGIC_USB
+       if (dwc->super_speed_support)
+               props[prop_idx++].name = "super_speed_support";
+#endif
+
        if (prop_idx) {
                ret = platform_device_add_properties(xhci, props);
                if (ret) {
@@ -113,11 +118,6 @@ int dwc3_host_init(struct dwc3 *dwc)
                }
        }
 
-#ifdef CONFIG_AMLOGIC_USB
-       if (dwc->super_speed_support)
-               props[prop_idx++].name = "usb3-support";
-#endif
-
        phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy",
                          dev_name(&xhci->dev));
        phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
index c2722b5..f9e9215 100644 (file)
@@ -238,7 +238,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
                xhci->quirks |= XHCI_BROKEN_PORT_PED;
 
 #ifdef CONFIG_AMLOGIC_USB
-       if (device_property_read_bool(&pdev->dev, "usb3-support"))
+       if (device_property_read_bool(&pdev->dev, "super_speed_support"))
                xhci->quirks |= XHCI_AML_SUPER_SPEED_SUPPORT;
 #endif
 
index 464fd2e..82291b3 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/amlogic/aml_gpio_consumer.h>
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
+#include <linux/clk.h>
 
 #define PHY_REGISTER_SIZE      0x20
 /* Register definitions */
@@ -171,6 +172,7 @@ struct amlogic_usb_v2 {
 
        int portnum;
        int suspend_flag;
+       struct clk              *clk;
 };
 
 #endif
index 0f5db62..0dd7b13 100644 (file)
 #define USB_CORE_RESET_TIME    10
 #define USB_ID_CHANGE_TIME     100
 
+enum usb3_phy_func_e {
+       AML_USB3_PHY_DISABLE = 0,
+       AML_USB3_PHY_ENABLE,
+};
+
 enum usb_port_type_e {
        USB_PORT_TYPE_OTG = 0,
        USB_PORT_TYPE_HOST,