From: make shi Date: Fri, 24 Aug 2012 05:53:49 +0000 (+0800) Subject: ENGR00221317-02 Mx6 USB host: set stop_mode_config when any USB host enabled X-Git-Tag: v3.0.35-fsl~549 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f2d727d4f18018aece6813e91506770fbf297135;p=karo-tx-linux.git 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 --- 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;