]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00221317-02 Mx6 USB host: set stop_mode_config when any USB host enabled
authormake shi <b15407@freescale.com>
Fri, 24 Aug 2012 05:53:49 +0000 (13:53 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:18 +0000 (08:35 +0200)
The Mx6 phy sometimes work abnormally after system suspend/resume if the 1V1
is off. So we should keep the 1V1 active during the system suspend if any USB
host enabled.
- Add stop_mode_config to 1 with refcount
- Add mutex to protect the refcount and HW_ANADIG_ANA_MISC0 register
- If stop_mode_config is set as 1, the otg  vbus wakeup system will be supported

Signed-off-by: make shi <b15407@freescale.com>
arch/arm/mach-mx6/pm.c
arch/arm/mach-mx6/usb_dr.c
arch/arm/mach-mx6/usb_h1.c
arch/arm/plat-mxc/usb_common.c

index 50df5714b2d88c706b91c23ee67849179bdde056..dd5db57c984bdce61d45defb088b2acd67263831 100644 (file)
@@ -38,6 +38,7 @@
 #endif
 #include "crm_regs.h"
 #include "src-reg.h"
+#include "regs-anadig.h"
 
 #define SCU_CTRL_OFFSET                                0x00
 #define GPC_IMR1_OFFSET                                0x08
@@ -118,6 +119,11 @@ static void usb_power_down_handler(void)
 {
        u32 temp;
        bool usb_oh3_clk_already_on;
+       if ((__raw_readl(anatop_base + HW_ANADIG_ANA_MISC0)
+               & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) != 0) {
+                       usb_vbus_wakeup_enabled = false;
+                       return;
+       }
        /* enable usb oh3 clock if needed*/
        temp = __raw_readl(MXC_CCM_CCGR6);
        usb_oh3_clk_already_on =        \
index 1efac33aa7fc0c35285d1c31792e2a602b062817..8cfcb27c7594be76fbb431c25a0a4cbb62cf5b79 100644 (file)
@@ -173,6 +173,9 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
 static int usbotg_init_ext(struct platform_device *pdev)
 {
        struct clk *usb_clk;
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+       void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+#endif
        u32 ret;
 
        /* at mx6q: this clock is AHB clock for usb core */
@@ -198,6 +201,12 @@ static int usbotg_init_ext(struct platform_device *pdev)
                mdelay(3);
        }
        otg_used++;
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+       usb_stop_mode_lock();
+       if (usb_stop_mode_refcount(true) == 1)
+               __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+       usb_stop_mode_unlock();
+#endif
 
        return ret;
 }
@@ -205,6 +214,9 @@ static int usbotg_init_ext(struct platform_device *pdev)
 static void usbotg_uninit_ext(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+       void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+#endif
 
        clk_disable(usb_phy1_clk);
        clk_put(usb_phy1_clk);
@@ -214,6 +226,12 @@ static void usbotg_uninit_ext(struct platform_device *pdev)
 
        usbotg_uninit(pdata);
        otg_used--;
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+       usb_stop_mode_lock();
+        if (usb_stop_mode_refcount(false) == 0)
+               __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
+        usb_stop_mode_unlock();
+#endif
 }
 
 static void usbotg_clock_gate(bool on)
index 92ef0ec3c3f548e1dc031d88d8f2459bebc39927..3e2f50ab6b55bc0930f29203beab6af3f1535a8a 100644 (file)
@@ -134,6 +134,7 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
 {
        int ret;
        struct clk *usb_clk;
+       void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
        usb_clk = clk_get(NULL, "usboh3_clk");
        clk_enable(usb_clk);
        usb_oh3_clk = usb_clk;
@@ -145,19 +146,25 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
        }
        usbh1_internal_phy_clock_gate(true);
        usb_phy_enable(pdev->dev.platform_data);
-
+       usb_stop_mode_lock();
+       if (usb_stop_mode_refcount(true) == 1)
+               __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+       usb_stop_mode_unlock();
        return 0;
 }
 
 static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-
+       void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
        fsl_usb_host_uninit(pdata);
 
        clk_disable(usb_oh3_clk);
        clk_put(usb_oh3_clk);
-
+       usb_stop_mode_lock();
+       if (usb_stop_mode_refcount(false) == 0)
+               __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
+       usb_stop_mode_unlock();
 }
 
 static void usbh1_clock_gate(bool on)
index 97d963a54a54a24126402b5c2df554b2b82b6848..d85d8d663571f8a94c6895fd541f2448fecca598 100755 (executable)
@@ -53,7 +53,9 @@ typedef void (*driver_vbus_func)(bool);
 
 void __iomem *imx_otg_base;
 static  driver_vbus_func s_driver_vbus;
+static int stop_mode_refcount;
 
+DEFINE_MUTEX(usb_common_mutex);
 EXPORT_SYMBOL(imx_otg_base);
 
 #define MXC_NUMBER_USB_TRANSCEIVER 6
@@ -71,6 +73,41 @@ bool usb_icbug_swfix_need(void)
 }
 EXPORT_SYMBOL(usb_icbug_swfix_need);
 
+/*
+  * The Mx6 phy sometimes work abnormally after system suspend/resume if the 1V1 is off.
+  * So we should keep the 1V1 active during the system suspend if any USB host enabled.
+  * Set stop_mode_config when any USB host enabled by default, it will impact on system power.
+  * #define DISABLE_STOP_MODE will disable the feature.
+  */
+#ifndef DISABLE_STOP_MODE
+int usb_stop_mode_refcount(bool enable)
+{
+       if (enable)
+               stop_mode_refcount++;
+       else
+               stop_mode_refcount--;
+       return stop_mode_refcount;
+}
+#else
+int usb_stop_mode_refcount(bool enable)
+{
+       return 0;
+}
+#endif
+EXPORT_SYMBOL(usb_stop_mode_refcount);
+
+void usb_stop_mode_lock(void)
+{
+       mutex_lock(&usb_common_mutex);
+}
+EXPORT_SYMBOL(usb_stop_mode_lock);
+
+void usb_stop_mode_unlock(void)
+{
+       mutex_unlock(&usb_common_mutex);
+}
+EXPORT_SYMBOL(usb_stop_mode_unlock);
+
 void mx6_set_host1_vbus_func(driver_vbus_func driver_vbus)
 {
        s_driver_vbus = driver_vbus;