Merge "USB: OTG: prevent idle standalone PC when USB cable is connected." into msm-3.0
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 06d63d9..b6acf41 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2154,6 +2154,8 @@
msm_otg_pdata.phy_init_seq =
liquid_v1_phy_init_seq;
}
+ msm_otg_pdata.swfi_latency =
+ msm_rpmrs_levels[0].latency_us;
#ifdef CONFIG_USB_EHCI_MSM_HSIC
if (machine_is_msm8960_liquid()) {
if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index ec922f1..c55ba6e 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -37,6 +37,7 @@
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
+#include <linux/pm_qos_params.h>
#include <mach/clk.h>
#include <mach/msm_xo.h>
@@ -63,6 +64,25 @@
static struct msm_otg *the_msm_otg;
static bool debug_aca_enabled;
+/* Prevent idle power collapse(pc) while operating in peripheral mode */
+static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
+{
+ struct msm_otg_platform_data *pdata = dev->pdata;
+ u32 swfi_latency = 0;
+
+ if (!pdata || !pdata->swfi_latency)
+ return;
+
+ swfi_latency = pdata->swfi_latency + 1;
+
+ if (vote)
+ pm_qos_update_request(&dev->pm_qos_req_dma,
+ swfi_latency);
+ else
+ pm_qos_update_request(&dev->pm_qos_req_dma,
+ PM_QOS_DEFAULT_VALUE);
+}
+
static struct regulator *hsusb_3p3;
static struct regulator *hsusb_1p8;
static struct regulator *hsusb_vddcx;
@@ -991,10 +1011,16 @@
*/
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
+ /*
+ * vote for minimum dma_latency to prevent idle
+ * power collapse(pc) while running in peripheral mode.
+ */
+ otg_pm_qos_update_latency(motg, 1);
usb_gadget_vbus_connect(otg->gadget);
} else {
dev_dbg(otg->dev, "gadget off\n");
usb_gadget_vbus_disconnect(otg->gadget);
+ otg_pm_qos_update_latency(motg, 0);
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
}
@@ -2240,6 +2266,10 @@
}
clk_set_rate(motg->clk, 60000000);
+ /* pm qos request to prevent apps idle power collapse */
+ if (motg->pdata->swfi_latency)
+ pm_qos_add_request(&motg->pm_qos_req_dma,
+ PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
/*
* If USB Core is running its protocol engine based on CORE CLK,
* CORE CLK must be running at >55Mhz for correct HSUSB
@@ -2460,6 +2490,8 @@
if (!IS_ERR(motg->phy_reset_clk))
clk_put(motg->phy_reset_clk);
free_motg:
+ if (motg->pdata->swfi_latency)
+ pm_qos_remove_request(&motg->pm_qos_req_dma);
kfree(motg);
return ret;
}
@@ -2535,8 +2567,10 @@
if (!IS_ERR(motg->system_clk))
clk_put(motg->system_clk);
- kfree(motg);
+ if (motg->pdata->swfi_latency)
+ pm_qos_remove_request(&motg->pm_qos_req_dma);
+ kfree(motg);
return 0;
}
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a2251fe..68fc67c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/usb/otg.h>
#include <linux/wakelock.h>
+#include <linux/pm_qos_params.h>
/**
* Supported USB modes
@@ -145,6 +146,7 @@
* dfab_usb_hs_clk in case of 8660 and 8960.
* @pmic_id_irq: IRQ number assigned for PMIC USB ID line.
* @mhl_enable: indicates MHL connector or not.
+ * @swfi_latency: miminum latency to allow swfi.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -158,6 +160,7 @@
const char *pclk_src_name;
int pmic_id_irq;
bool mhl_enable;
+ u32 swfi_latency;
};
/**
@@ -188,6 +191,8 @@
* connected. Useful only when ACA_A charger is
* connected.
* @mA_port: The amount of current drawn by the attached B-device.
+ * @pm_qos_req_dma: miminum DMA latency to vote against idle power
+ collapse when cable is connected.
* @id_timer: The timer used for polling ID line to detect ACA states.
* @xo_handle: TCXO buffer handle
*/
@@ -244,6 +249,7 @@
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
#define PHY_OTG_COMP_DISABLED BIT(2)
+ struct pm_qos_request_list pm_qos_req_dma;
};
struct msm_hsic_host_platform_data {