usb: enable usb suspend.
authorYue Wang <yue.wang@amlogic.com>
Mon, 12 Mar 2018 02:30:41 +0000 (10:30 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Thu, 22 Mar 2018 05:49:26 +0000 (21:49 -0800)
PD#161622: usb: enable usb suspend.

Change-Id: I28e2ac7855dbdfe0299592189af179575a264272
Signed-off-by: Yue Wang <yue.wang@amlogic.com>
arch/arm64/boot/dts/amlogic/mesong12a.dtsi
drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h
drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c
drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c
drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c
drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c
drivers/usb/host/xhci-mem.c

index b8b366d..0919f81 100644 (file)
                compatible = "amlogic, amlogic-new-usb2-v2";
                status = "disable";
                reg = <0x0 0xffe09000 0x0 0x80
-                               0x0 0xffd01008 0x0 0x4
+                               0x0 0xffd01008 0x0 0x100
                                0x0 0xff636000 0x0 0x2000
                                0x0 0xff63a000 0x0 0x2000>;
                pll-setting-1 = <0x09400414>;
index 707b206..ce90831 100644 (file)
@@ -88,6 +88,8 @@ typedef struct dwc_otg_device {
        struct notifier_block nb;
 
        struct delayed_work     work;
+
+       u32 host_plug;
 } dwc_otg_device_t;
 
 /*We must clear S3C24XX_EINTPEND external interrupt register
index 264749b..e5c8644 100644 (file)
@@ -1057,7 +1057,21 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd)
            GET_CORE_IF(pcd)->core_global_regs;
        uint8_t utmi16b, utmi8b;
        int speed;
+       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+
        DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
+       if (core_if->controller_type == USB_OTG) {
+               if (core_if->phy_interface == 0) {
+                       if (pcd->otg_dev->host_plug) {
+                               gintsts.d32 = 0;
+                               gintsts.b.enumdone = 1;
+                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
+                                       core_global_regs->gintsts, gintsts.d32);
+                               DWC_DEBUGPL(DBG_PCD, "false speed emun\n");
+                               return 1;
+                       }
+               }
+       }
 
        if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
                utmi16b = 6;
index f4cb084..0565f09 100644 (file)
@@ -1258,16 +1258,27 @@ int dwc_usb_change(struct notifier_block *nb,
                              unsigned long value, void *pdata)
 {
        dwc_otg_device_t *otg_dev;
+       dwc_otg_core_global_regs_t *global_regs;
 
        otg_dev = container_of(nb, dwc_otg_device_t, nb);
+       global_regs = otg_dev->core_if->core_global_regs;
 
        if (value) {
                DWC_DEBUGPL(DBG_PCDV, "start usb device\n");
+               otg_dev->host_plug = 0;
                dwc_otg_enable_global_interrupts(otg_dev->core_if);
+               if (otg_dev->core_if->phy_interface == 0)
+                       dwc_otg_enable_device_interrupts(otg_dev->core_if);
                otg_dev->pcd->core_if->pcd_cb->start(otg_dev->pcd);
        } else {
+               otg_dev->host_plug = 1;
                DWC_DEBUGPL(DBG_PCDV, "stop usb device\n");
                dwc_otg_disable_global_interrupts(otg_dev->core_if);
+
+               /* Disable all interrupts. */
+               if (otg_dev->core_if->phy_interface == 0)
+                       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
+
                otg_dev->pcd->core_if->pcd_cb->stop(otg_dev->pcd);
        }
 
index 86eaa35..1fdf8f9 100644 (file)
@@ -47,20 +47,12 @@ static int amlogic_new_usb2_init(struct usb_phy *x)
        struct u2p_aml_regs_v2 u2p_aml_regs;
        union u2p_r0_v2 reg0;
        union u2p_r1_v2 reg1;
-       //u32 val;
+       u32 val;
 
-       if (phy->suspend_flag) {
-               phy->suspend_flag = 0;
-               for (i = 0; i < phy->portnum; i++) {
-                       for (j = 0; j < 2; j++) {
-                               u2p_aml_regs.u2p_r_v2[j] = (void __iomem *)
-                               ((unsigned long)phy->regs + i*PHY_REGISTER_SIZE
-                                       + 4 * j);
-                       }
-               }
-               /*TO DO: set usb phy to low power mode*/
-               return 0;
-       }
+       val = readl((void __iomem *)
+               ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8)));
+       writel((val | (0x3 << 16)), (void __iomem *)
+               ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8)));
 
        amlogic_new_usbphy_reset_v2(phy);
 
@@ -73,9 +65,13 @@ static int amlogic_new_usb2_init(struct usb_phy *x)
 
                reg0.d32 = readl(u2p_aml_regs.u2p_r_v2[0]);
                reg0.b.POR = 1;
-               reg0.b.host_device = 1;
-               if (i == 1)
-                       reg0.b.IDPULLUP0 = 1;
+               if (phy->suspend_flag == 0) {
+                       reg0.b.host_device = 1;
+                       if (i == 1) {
+                               reg0.b.IDPULLUP0 = 1;
+                               reg0.b.DRVVBUS0 = 1;
+                       }
+               }
 
                writel(reg0.d32, u2p_aml_regs.u2p_r_v2[0]);
 
@@ -120,19 +116,15 @@ static int amlogic_new_usb2_suspend(struct usb_phy *x, int suspend)
 static void amlogic_new_usb2phy_shutdown(struct usb_phy *x)
 {
        struct amlogic_usb_v2 *phy = phy_to_amlusb(x);
-       struct u2p_aml_regs_v2 u2p_aml_regs;
-       int i, j;
+       u32 val;
 
-       phy->suspend_flag = 1;
-       for (i = phy->portnum - 1; i >= 0; i--) {
-               for (j = 0; j < 2; j++) {
-                       u2p_aml_regs.u2p_r_v2[j] = (void __iomem        *)
-                               ((unsigned long)phy->regs + i*PHY_REGISTER_SIZE
-                               + 4 * j);
-               }
+       /* set usb phy to low power mode */
+       val = readl((void __iomem               *)
+               ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8)));
+       writel((val & (~(0x3 << 16))), (void __iomem    *)
+               ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8)));
 
-               /*TO DO: set usb phy to low power mode*/
-       }
+       phy->suspend_flag = 1;
 }
 
 static int amlogic_new_usb2_probe(struct platform_device *pdev)
@@ -210,7 +202,6 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev)
        phy->regs               = phy_base;
        phy->reset_regs = reset_base;
        phy->portnum      = portnum;
-       phy->suspend_flag = 0;
        phy->phy.dev            = phy->dev;
        phy->phy.label          = "amlogic-usbphy2";
        phy->phy.init           = amlogic_new_usb2_init;
@@ -220,6 +211,7 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev)
        phy->pll_setting[0] = pll_setting[0];
        phy->pll_setting[1] = pll_setting[1];
        phy->pll_setting[2] = pll_setting[2];
+       phy->suspend_flag = 0;
        for (i = 0; i < portnum; i++)
                phy->phy_cfg[i] = phy_cfg_base[i];
 
index f24bedd..fd06de2 100644 (file)
@@ -70,7 +70,6 @@ static void aml_new_usb_notifier_call(unsigned long is_device_on)
        blocking_notifier_call_chain
                        (&aml_new_usb_v2_notifier_list, is_device_on, NULL);
 }
-//EXPORT_SYMBOL(aml_new_usb_notifier_call);
 
 static void set_usb_vbus_power
        (struct gpio_desc *usb_gd, int pin, char is_power_on)
@@ -100,6 +99,9 @@ static void amlogic_new_usb3phy_shutdown(struct usb_phy *x)
 {
        struct amlogic_usb_v2 *phy = phy_to_amlusb(x);
 
+       if (phy->phy.flags == AML_USB3_PHY_ENABLE)
+               clk_disable_unprepare(phy->clk);
+
        phy->suspend_flag = 1;
 }
 
@@ -128,6 +130,8 @@ static int amlogic_new_usb3_init(struct usb_phy *x)
        int i = 0;
 
        if (phy->suspend_flag) {
+               if (phy->phy.flags == AML_USB3_PHY_ENABLE)
+                       clk_prepare_enable(phy->clk);
                phy->suspend_flag = 0;
                return 0;
        }
@@ -148,7 +152,7 @@ static int amlogic_new_usb3_init(struct usb_phy *x)
        writel(r5.d32, usb_new_aml_regs_v2.usb_r_v2[5]);
 
        /* config usb3 phy */
-       if (phy->portnum > 0) {
+       if (phy->phy.flags == AML_USB3_PHY_ENABLE) {
                r3.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[3]);
                r3.b.p30_ssc_en = 1;
                r3.b.p30_ref_ssp_en = 1;
index ac8b4a3..1375915 100644 (file)
@@ -2252,7 +2252,14 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                }
                xhci->port_array[i] = major_revision;
                if (major_revision == 0x03)
+#ifdef CONFIG_AMLOGIC_USB
+                       if (xhci->quirks & XHCI_AML_SUPER_SPEED_SUPPORT)
+                               xhci->num_usb3_ports++;
+                       else
+                               xhci->num_usb3_ports = 0;
+#else
                        xhci->num_usb3_ports++;
+#endif
                else
                        xhci->num_usb2_ports++;
        }