Commit c6f69925 authored by make shi's avatar make shi

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: default avatarmake shi <b15407@freescale.com>
parent cc2e5136
......@@ -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 = \
......
......@@ -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)
......
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment