diff options
Diffstat (limited to 'arch/arm/mach-tegra/baseband-xmm-power.c')
-rw-r--r-- | arch/arm/mach-tegra/baseband-xmm-power.c | 249 |
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; } |