usb: gadget: HSIC wake from suspend workaround
For some MSM targets, there is an HW limitation that doesn't
allow wakeing up from USB bus suspend, when certain USB core
clocks are turned off as part of runtime suspend.
When this workaround is turned ON, the clocks that are mandatory
will not be disabled on runtime suspend.
Change-Id: Iab397c4f3b2918a5aa5eef7a60123bf7ede58d81
Signed-off-by: Amit Blay <ablay@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 7e9833b..a8602d3 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -569,6 +569,10 @@
.disable_reset_on_disconnect = true,
};
+static struct msm_hsic_peripheral_platform_data msm_hsic_peripheral_pdata = {
+ .keep_core_clk_on_suspend_workaround = true,
+};
+
#define PID_MAGIC_ID 0x71432909
#define SERIAL_NUM_MAGIC_ID 0x61945374
#define SERIAL_NUMBER_LENGTH 127
@@ -757,6 +761,8 @@
msm_device_otg.dev.platform_data = &msm_otg_pdata;
msm_otg_pdata.phy_init_seq = shelby_phy_init_seq;
+ msm_device_hsic_peripheral.dev.platform_data =
+ &msm_hsic_peripheral_pdata;
msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index eeacceb..39d4720 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -65,6 +65,7 @@
struct msm_xo_voter *xo_handle;
struct workqueue_struct *wq;
struct work_struct suspend_w;
+ struct msm_hsic_peripheral_platform_data *pdata;
};
static int msm_hsic_init_vddcx(struct msm_hsic_per *mhsic, int init)
@@ -365,8 +366,10 @@
*/
mb();
- clk_disable(mhsic->iface_clk);
- clk_disable(mhsic->core_clk);
+ if (!mhsic->pdata->keep_core_clk_on_suspend_workaround) {
+ clk_disable(mhsic->iface_clk);
+ clk_disable(mhsic->core_clk);
+ }
clk_disable(mhsic->phy_clk);
clk_disable(mhsic->cal_clk);
@@ -416,8 +419,10 @@
dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
__func__, ret);
- clk_enable(mhsic->iface_clk);
- clk_enable(mhsic->core_clk);
+ if (!mhsic->pdata->keep_core_clk_on_suspend_workaround) {
+ clk_enable(mhsic->iface_clk);
+ clk_enable(mhsic->core_clk);
+ }
clk_enable(mhsic->phy_clk);
clk_enable(mhsic->cal_clk);
@@ -611,9 +616,17 @@
struct resource *res;
struct msm_hsic_per *mhsic;
int ret = 0;
+ struct msm_hsic_peripheral_platform_data *pdata;
dev_dbg(&pdev->dev, "msm-hsic probe\n");
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "No platform data given. Bailing out\n");
+ return -ENODEV;
+ } else {
+ pdata = pdev->dev.platform_data;
+ }
+
mhsic = kzalloc(sizeof(struct msm_hsic_per), GFP_KERNEL);
if (!mhsic) {
dev_err(&pdev->dev, "unable to allocate msm_hsic\n");
@@ -622,6 +635,7 @@
the_mhsic = mhsic;
platform_set_drvdata(pdev, mhsic);
mhsic->dev = &pdev->dev;
+ mhsic->pdata = pdata;
mhsic->irq = platform_get_irq(pdev, 0);
if (mhsic->irq < 0) {
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index cf6bb4b..b53d9dd 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -342,6 +342,10 @@
unsigned int dock_connect_irq;
};
+struct msm_hsic_peripheral_platform_data {
+ bool keep_core_clk_on_suspend_workaround;
+};
+
struct usb_bam_pipe_connect {
u32 src_phy_addr;
int src_pipe_index;