summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2012-05-16 18:45:02 -0700
committerVarun Colbert <vcolbert@nvidia.com>2012-06-15 11:12:38 -0700
commitea957c2de09b608a55b49f1ec1408a16d65308a5 (patch)
tree17849d98d93fb7ec14525fa3a507c7825485279e
parent23a7238b83e549e511decba6816d25d6bda80bb8 (diff)
arm: tegra: xmm: removing L3 state transition
Remove L3 state from xmm power driver. New usb phy code allows pm state transition L0->L2 and L2->L0. When the system goes in LP0/LP1 suspend then the modem power state is kept at L2 and bus state in suspend controlled by PMC. At system resume the hsic bus is given back to USB. Bug 991709 Change-Id: Ib3b74d7da30a5103eddd747726ac7c4423472c76 Signed-off-by: Vinayak Pane <vpane@nvidia.com> Reviewed-on: http://git-master/r/108076 Reviewed-by: Michael Hsu <mhsu@nvidia.com> Reviewed-by: Steve Lin <stlin@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c249
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c2
2 files changed, 88 insertions, 163 deletions
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index 30aba86f02f1..36f5fc6611f9 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -121,10 +121,6 @@ static struct delayed_work pm_qos_work;
struct xmm_power_data xmm_power_drv_data;
EXPORT_SYMBOL(xmm_power_drv_data);
-static void xmm_power_L2_resume(void);
-static int xmm_power_driver_handle_resume(
- struct baseband_power_platform_data *data);
-
static int tegra_baseband_rail_on(void)
{
int ret;
@@ -408,6 +404,65 @@ static void pm_qos_worker(struct work_struct *work)
static DEVICE_ATTR(xmm_onoff, S_IRUSR | S_IWUSR | S_IRGRP,
NULL, xmm_onoff);
+/* Do the work for AP/CP initiated L2->L0 */
+static void xmm_power_l2_resume(void)
+{
+ struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
+ struct xmm_power_data *drv = &xmm_power_drv_data;
+ int value;
+ int delay = 1000; /* maxmum delay in msec */
+ unsigned long flags;
+ int ret, rcount = 0;
+
+ pr_debug("%s\n", __func__);
+
+ if (!pdata)
+ return;
+
+ /* claim the wakelock here to avoid any system suspend */
+ if (!wake_lock_active(&wakelock))
+ wake_lock_timeout(&wakelock, HZ*2);
+ modem_sleep_flag = false;
+ spin_lock_irqsave(&xmm_lock, flags);
+ wakeup_pending = false;
+ spin_unlock_irqrestore(&xmm_lock, flags);
+
+ if (CP_initiated_L2toL0) {
+ pr_info("CP L2->L0\n");
+ CP_initiated_L2toL0 = false;
+ queue_work(workqueue, &L2_resume_work);
+ } else {
+ /* set the slave wakeup request */
+ pr_info("AP/CP L2->L0\n");
+ value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
+ if (value) {
+ drv->hostwake = 0;
+ /* wake bb */
+ gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
+retry:
+ /* wait for cp */
+ pr_debug("waiting for host wakeup from CP...\n");
+ ret = wait_event_interruptible_timeout(drv->bb_wait,
+ drv->hostwake == 1, msecs_to_jiffies(delay));
+ if (ret == 0) {
+ pr_info("!!AP L2->L0 Failed\n");
+ return;
+ }
+ if (ret == -ERESTARTSYS) {
+ if (rcount >= 5) {
+ pr_info("!!AP L2->L0 Failed\n");
+ return;
+ }
+ pr_debug("%s: caught signal\n", __func__);
+ rcount++;
+ goto retry;
+ }
+ pr_debug("Get gpio host wakeup low <-\n");
+ } else
+ pr_info("CP already ready\n");
+ }
+}
+
void baseband_xmm_set_power_status(unsigned int status)
{
@@ -421,25 +476,24 @@ void baseband_xmm_set_power_status(unsigned int status)
switch (status) {
case BBXMM_PS_L0:
if (modem_sleep_flag) {
- pr_info("%s Resume from L3 without calling resume"
- "function\n", __func__);
- xmm_power_driver_handle_resume(data);
+ /* We dont have L3 state now, should be handled from L2
+ * xmm_power_driver_handle_resume(data);
+ */
}
pr_info("L0\n");
baseband_xmm_powerstate = status;
if (!wake_lock_active(&wakelock))
- wake_lock(&wakelock);
+ wake_lock_timeout(&wakelock, HZ*2);
value = gpio_get_value(data->modem.xmm.ipc_hsic_active);
pr_debug("before L0 ipc_hsic_active=%d\n", value);
if (!value) {
- pr_debug("before L0 gpio set ipc_hsic_active=1 ->\n");
+ pr_debug("L0 gpio set ipc_hsic_active=1 ->\n");
gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
}
if (modem_power_on) {
modem_power_on = false;
baseband_modem_power_on(data);
}
- pr_debug("gpio host active high->\n");
break;
case BBXMM_PS_L2:
pr_info("L2\n");
@@ -447,7 +501,8 @@ void baseband_xmm_set_power_status(unsigned int status)
spin_lock_irqsave(&xmm_lock, flags);
if (wakeup_pending) {
spin_unlock_irqrestore(&xmm_lock, flags);
- xmm_power_L2_resume();
+ pr_debug("%s: wakeup pending\n", __func__);
+ xmm_power_l2_resume();
} else {
spin_unlock_irqrestore(&xmm_lock, flags);
if (wake_lock_active(&wakelock))
@@ -455,34 +510,8 @@ void baseband_xmm_set_power_status(unsigned int status)
modem_sleep_flag = true;
}
break;
- case BBXMM_PS_L3:
- if (baseband_xmm_powerstate == BBXMM_PS_L2TOL0) {
- if (!data->modem.xmm.ipc_ap_wake) {
- spin_lock_irqsave(&xmm_lock, flags);
- wakeup_pending = true;
- spin_unlock_irqrestore(&xmm_lock, flags);
- pr_info("%s: L2 race condition-CP wakeup"
- " pending\n", __func__);
- }
- }
- pr_info("L3\n");
- /* system is going to suspend */
- if (baseband_xmm_powerstate == BBXMM_PS_L2)
- tegra_baseband_rail_off();
-
- baseband_xmm_powerstate = status;
- spin_lock_irqsave(&xmm_lock, flags);
- system_suspending = false;
- spin_unlock_irqrestore(&xmm_lock, flags);
- if (wake_lock_active(&wakelock)) {
- pr_info("%s: releasing wakelock before L3\n",
- __func__);
- wake_unlock(&wakelock);
- }
- gpio_set_value(data->modem.xmm.ipc_hsic_active, 0);
- pr_debug("gpio host active low->\n");
- break;
case BBXMM_PS_L2TOL0:
+ pr_debug("L2TOL0\n");
spin_lock_irqsave(&xmm_lock, flags);
system_suspending = false;
wakeup_pending = false;
@@ -491,16 +520,11 @@ void baseband_xmm_set_power_status(unsigned int status)
if (baseband_xmm_powerstate == BBXMM_PS_L2) {
baseband_xmm_powerstate = status;
pr_debug("BB XMM POWER STATE = %d\n", status);
- xmm_power_L2_resume();
+ xmm_power_l2_resume();
}
baseband_xmm_powerstate = status;
break;
- case BBXMM_PS_L3TOL0:
- /* poweron rail for L3 -> L0 (system resume) */
- pr_debug("L3 -> L0, turning on power rail.\n");
- tegra_baseband_rail_on();
- baseband_xmm_powerstate = status;
- break;
+
default:
baseband_xmm_powerstate = status;
break;
@@ -571,11 +595,7 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
pr_info("Set wakeup_pending = 1 in system_"
" suspending!!!\n");
} else {
- if ((baseband_xmm_powerstate == BBXMM_PS_L3) ||
- (baseband_xmm_powerstate == BBXMM_PS_L3TOL0)) {
- spin_unlock(&xmm_lock);
- pr_info(" CP L3 -> L0\n");
- } else if (baseband_xmm_powerstate == BBXMM_PS_L2) {
+ if (baseband_xmm_powerstate == BBXMM_PS_L2) {
CP_initiated_L2toL0 = true;
spin_unlock(&xmm_lock);
baseband_xmm_set_power_status(BBXMM_PS_L2TOL0);
@@ -686,67 +706,8 @@ static void xmm_power_autopm_resume(struct work_struct *work)
}
-/* Do the work for AP/CP initiated L2->L0 */
-static void xmm_power_L2_resume(void)
-{
- struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
- struct xmm_power_data *drv = &xmm_power_drv_data;
- int value;
- int delay = 1000; /* maxmum delay in msec */
- unsigned long flags;
- int ret, rcount = 0;
-
- pr_debug("%s\n", __func__);
-
- if (!pdata)
- return;
-
- /* claim the wakelock here to avoid any system suspend */
- if (!wake_lock_active(&wakelock))
- wake_lock(&wakelock);
- modem_sleep_flag = false;
- spin_lock_irqsave(&xmm_lock, flags);
- wakeup_pending = false;
- spin_unlock_irqrestore(&xmm_lock, flags);
-
- if (CP_initiated_L2toL0) {
- pr_info("CP L2->L0\n");
- CP_initiated_L2toL0 = false;
- queue_work(workqueue, &L2_resume_work);
- } else {
- /* set the slave wakeup request */
- pr_info("AP L2->L0\n");
- value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
- if (value) {
- drv->hostwake = 0;
- /* wake bb */
- gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
-retry:
- /* wait for cp */
- pr_debug("waiting for host wakeup from CP...\n");
- ret = wait_event_interruptible_timeout(drv->bb_wait,
- drv->hostwake == 1, msecs_to_jiffies(delay));
- if (ret == 0) {
- pr_info("!!AP L2->L0 Failed\n");
- return;
- }
- if (ret == -ERESTARTSYS) {
- if (rcount >= 5) {
- pr_info("!!AP L2->L0 Failed\n");
- return;
- }
- pr_debug("%s: caught signal\n", __func__);
- rcount++;
- goto retry;
- }
- pr_debug("Get gpio host wakeup low <-\n");
- } else
- pr_info("CP already ready\n");
- }
-}
-
/* Do the work for CP initiated L2->L0 */
-static void xmm_power_L2_resume_work(struct work_struct *work)
+static void xmm_power_l2_resume_work(struct work_struct *work)
{
struct usb_interface *intf;
@@ -1030,7 +991,7 @@ static int xmm_power_driver_probe(struct platform_device *device)
/* init work objects */
INIT_WORK(&init1_work, xmm_power_init1_work);
INIT_WORK(&init2_work, xmm_power_init2_work);
- INIT_WORK(&L2_resume_work, xmm_power_L2_resume_work);
+ INIT_WORK(&L2_resume_work, xmm_power_l2_resume_work);
INIT_WORK(&autopm_resume_work, xmm_power_autopm_resume);
/* init state variables */
@@ -1088,71 +1049,35 @@ static int xmm_power_driver_remove(struct platform_device *device)
return 0;
}
-static int xmm_power_driver_handle_resume(
- struct baseband_power_platform_data *pdata)
+#ifdef CONFIG_PM
+static int xmm_power_driver_suspend(struct device *dev)
{
- int value;
- unsigned long timeout;
- unsigned long flags;
-
pr_debug("%s\n", __func__);
- if (!pdata)
- return 0;
/* check if modem is on */
if (power_onoff == 0) {
pr_debug("%s - flight mode - nop\n", __func__);
return 0;
}
-
- modem_sleep_flag = false;
- spin_lock_irqsave(&xmm_lock, flags);
- wakeup_pending = false;
- spin_unlock_irqrestore(&xmm_lock, flags);
-
- /* L3->L0 */
- baseband_xmm_set_power_status(BBXMM_PS_L3TOL0);
- value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
- if (value) {
- pr_info("AP L3 -> L0\n");
- /* wake bb */
- gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
-
- /* Wait for max 1 sec */
- timeout = jiffies + HZ;
- pr_debug("Current: %lu: timeout %lu\n", jiffies, timeout);
- do {
- udelay(100);
- value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
- if (!value)
- break;
- } while (time_before(jiffies, timeout));
- if (!value)
- pr_debug("gpio host wakeup low <-\n");
- else
- pr_info("!!AP L3->L0 Failed\n");
- } else
- pr_info("CP L3 -> L0\n");
-
- reenable_autosuspend = true;
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int xmm_power_driver_suspend(struct device *dev)
-{
- pr_debug("%s\n", __func__);
+ /* PMC is driving hsic bus
+ * tegra_baseband_rail_off();
+ */
return 0;
}
static int xmm_power_driver_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct baseband_power_platform_data *pdata = pdev->dev.platform_data;
-
pr_debug("%s\n", __func__);
- xmm_power_driver_handle_resume(pdata);
+
+ /* check if modem is on */
+ if (power_onoff == 0) {
+ pr_debug("%s - flight mode - nop\n", __func__);
+ return 0;
+ }
+ /* PMC is driving hsic bus
+ * tegra_baseband_rail_on();
+ */
+ reenable_autosuspend = true;
return 0;
}
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index fb873a834138..2b5a72518d7c 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -639,7 +639,7 @@ static void enterprise_usb_hsic_post_phy_off(void)
{
pr_debug("%s\n", __func__);
#ifdef CONFIG_TEGRA_BB_XMM_POWER
- baseband_xmm_set_power_status(BBXMM_PS_L3);
+ baseband_xmm_set_power_status(BBXMM_PS_L2);
#endif
}