From 09e5ee34b53cdb278b52c05ba2e7b565e7d211a0 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Fri, 2 Feb 2018 19:41:59 +0800 Subject: [PATCH] usb: add usb3.0 driver support for g12a PD#156734: usb: add usb3.0 driver support for g12a Change-Id: Iac057b29d041a5c80114407df0ccd965aae11ca1 Signed-off-by: Yue Wang --- arch/arm64/boot/dts/amlogic/g12a_skt.dts | 3 +- drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c | 62 ++++++++++++++++++++++++--- drivers/usb/dwc3/core.c | 18 +++++--- drivers/usb/dwc3/host.c | 10 ++--- drivers/usb/host/xhci-plat.c | 2 +- include/linux/amlogic/usb-v2.h | 2 + include/linux/amlogic/usbtype.h | 5 +++ 7 files changed, 83 insertions(+), 19 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/g12a_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_skt.dts index 4ca6bca..9b956e34 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_skt.dts @@ -441,7 +441,6 @@ clock-src = "usb3.0"; clocks = <&clkc CLKID_USB_GENERAL>; clock-names = "dwc_general"; - /*snps,super_speed_support;*/ }; usb2_phy_v2: usb2phy@ffe09000 { @@ -463,6 +462,8 @@ phy-reg-size = <0x4>; interrupts = <0 16 4>; otg = <0>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; }; dwc2_a { diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 316f7f6..25328c0 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -31,6 +31,7 @@ #include #include #include +#include #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); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a2926a6..5a5ad4f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -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; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 2ea098c..fe075ac 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -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", diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index c2722b5..f9e9215 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -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 diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index 464fd2e..82291b3 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -23,6 +23,7 @@ #include #include #include +#include #define PHY_REGISTER_SIZE 0x20 /* Register definitions */ @@ -171,6 +172,7 @@ struct amlogic_usb_v2 { int portnum; int suspend_flag; + struct clk *clk; }; #endif diff --git a/include/linux/amlogic/usbtype.h b/include/linux/amlogic/usbtype.h index 0f5db62..0dd7b13 100644 --- a/include/linux/amlogic/usbtype.h +++ b/include/linux/amlogic/usbtype.h @@ -40,6 +40,11 @@ #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, -- 2.7.4