summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authormake shi <b15407@freescale.com>2012-08-24 13:53:49 +0800
committermake shi <b15407@freescale.com>2012-08-24 14:19:26 +0800
commitc6f69925f9d1f39ccc8c6fcc583122fcf03c105c (patch)
tree2069424fab91373adeabd657eff3bfb1d9438cf9 /arch
parentcc2e51368f2620a37370746eaf35f0b70674b31e (diff)
ENGR00221317-02 Mx6 USB host: set stop_mode_config when any USB host enabled
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx6/pm.c6
-rw-r--r--arch/arm/mach-mx6/usb_dr.c18
-rw-r--r--arch/arm/mach-mx6/usb_h1.c13
-rwxr-xr-xarch/arm/plat-mxc/usb_common.c37
4 files changed, 71 insertions, 3 deletions
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
index 50df5714b2d8..dd5db57c984b 100644
--- a/arch/arm/mach-mx6/pm.c
+++ b/arch/arm/mach-mx6/pm.c
@@ -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 = \
diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c
index 1efac33aa7fc..8cfcb27c7594 100644
--- a/arch/arm/mach-mx6/usb_dr.c
+++ b/arch/arm/mach-mx6/usb_dr.c
@@ -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)
diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c
index 92ef0ec3c3f5..3e2f50ab6b55 100644
--- a/arch/arm/mach-mx6/usb_h1.c
+++ b/arch/arm/mach-mx6/usb_h1.c
@@ -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)
diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c
index 97d963a54a54..d85d8d663571 100755
--- a/arch/arm/plat-mxc/usb_common.c
+++ b/arch/arm/plat-mxc/usb_common.c
@@ -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;