arm: tegra: xmm: removing L3 state transition
Vinayak Pane [Thu, 17 May 2012 01:45:02 +0000 (18:45 -0700)]
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/108440
(cherry picked from commit 2c34eb5496ce163a7857877220a403bd9e84c811)

Signed-off-by: Pritesh Raithatha <praithatha@nvidia.com>
Change-Id: I2e85796595a042777412d933405f6440fa21b2e7
Reviewed-on: http://git-master/r/109543
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>

arch/arm/mach-tegra/baseband-xmm-power.c
arch/arm/mach-tegra/board-enterprise.c

index 80fd4f4..d909afb 100644 (file)
@@ -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;
 }
index ea3328a..34bc575 100644 (file)
@@ -644,7 +644,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
 }