summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/baseband-xmm-power.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/baseband-xmm-power.c')
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c249
1 files changed, 87 insertions, 162 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;
}