summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2012-08-23 19:48:12 -0700
committerSimone Willett <swillett@nvidia.com>2012-09-06 14:21:58 -0700
commite96e462aee43ed8699f5cd64728c389e92ef402e (patch)
tree3bd09235aee88a464ee032d36a3303c8da65c6fe /arch
parent9bc5ccb125f8c32733a73bbc560ee71ac143f359 (diff)
arm: tegra: xmm: add post_resume phy callback
phy post_resume is called when usb port+hub is resumed, check if modem has finished resume by then. Notify modem about post resume by setting bb_wake to low. Modify check for CP initiated wakeup to read current modem state (ap_wake). Bug 1034420 Change-Id: Ie9a3aa581bd7660183464e3fc2554ceb055b69b2 Signed-off-by: Vinayak Pane <vpane@nvidia.com> Reviewed-on: http://git-master/r/129533 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c92
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c10
2 files changed, 57 insertions, 45 deletions
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index 5a7cecde526b..59e0779047b9 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -92,6 +92,7 @@ static int power_onoff;
static int reenable_autosuspend;
static bool wakeup_pending;
static bool modem_sleep_flag;
+static bool modem_acked_resume;
static spinlock_t xmm_lock;
static DEFINE_MUTEX(xmm_onoff_mutex);
static bool system_suspending;
@@ -259,6 +260,7 @@ static int xmm_power_on(struct platform_device *device)
/* reset the state machine */
baseband_xmm_set_power_status(BBXMM_PS_INIT);
modem_sleep_flag = false;
+ modem_acked_resume = true;
pr_debug("%s wake_st(%d) modem version %lu\n", __func__,
ipc_ap_wake_state, modem_ver);
@@ -466,41 +468,37 @@ static void xmm_power_l2_resume(void)
modem_sleep_flag = false;
wakeup_pending = false;
- if (cp_initiated_l2tol0) {
- cp_initiated_l2tol0 = false;
- queue_work(workqueue, &l2_resume_work);
- spin_unlock_irqrestore(&xmm_lock, flags);
- pr_info("CP L2->L0\n");
- } else {
- /* set the slave wakeup request */
- value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
+ value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
+ if (value) {
+ /* set the slave wakeup request - bb_wake high */
+ drv->hostwake = 0;
+ gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
spin_unlock_irqrestore(&xmm_lock, flags);
- if (value) {
- pr_info("AP/CP L2->L0\n");
- drv->hostwake = 0;
- /* wake bb */
- gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
+ pr_info("AP L2->L0\n");
retry:
- /* wait for cp */
- pr_debug("waiting for host wakeup from CP...\n");
- ret = wait_event_interruptible_timeout(drv->bb_wait,
+ /* 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) {
+ 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;
}
- 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");
+ pr_debug("%s: caught signal\n", __func__);
+ rcount++;
+ goto retry;
+ }
+ pr_debug("Get gpio host wakeup low <-\n");
+ } else {
+ cp_initiated_l2tol0 = false;
+ queue_work(workqueue, &l2_resume_work);
+ spin_unlock_irqrestore(&xmm_lock, flags);
+ pr_info("CP L2->L0\n");
}
}
@@ -521,16 +519,12 @@ void baseband_xmm_set_power_status(unsigned int status)
spin_lock_irqsave(&xmm_lock, flags);
switch (status) {
case BBXMM_PS_L0:
- if (modem_sleep_flag) {
- /* We dont have L3 state now, should be handled from L2
- * xmm_power_driver_handle_resume(data);
- */
- }
baseband_xmm_powerstate = status;
if (!wake_lock_active(&wakelock))
wake_lock_timeout(&wakelock, HZ*2);
+
+ /* pull hsic_active high for enumeration */
value = gpio_get_value(data->modem.xmm.ipc_hsic_active);
- pr_debug("before L0 ipc_hsic_active=%d\n", value);
if (!value) {
pr_debug("L0 gpio set ipc_hsic_active=1 ->\n");
gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
@@ -539,19 +533,31 @@ void baseband_xmm_set_power_status(unsigned int status)
modem_power_on = false;
baseband_modem_power_on(data);
}
+
+ /* cp acknowledgment for ap L2->L0 wake */
+ if (!modem_acked_resume)
+ pr_err("%s: CP didn't ack usb-resume\n", __func__);
+ value = gpio_get_value(data->modem.xmm.ipc_bb_wake);
+ if (value) {
+ /* clear the slave wakeup request */
+ gpio_set_value(data->modem.xmm.ipc_bb_wake, 0);
+ pr_debug("gpio bb_wake done low\n");
+ }
break;
case BBXMM_PS_L2:
- baseband_xmm_powerstate = status;
+ modem_acked_resume = false;
if (wakeup_pending) {
spin_unlock_irqrestore(&xmm_lock, flags);
pr_debug("%s: wakeup pending\n", __func__);
xmm_power_l2_resume();
spin_lock_irqsave(&xmm_lock, flags);
+ break;
} else {
if (wake_lock_active(&wakelock))
wake_unlock(&wakelock);
modem_sleep_flag = true;
}
+ baseband_xmm_powerstate = status;
break;
case BBXMM_PS_L2TOL0:
pr_debug("L2TOL0\n");
@@ -588,7 +594,6 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int value)
spin_lock(&xmm_lock);
/* AP L2 to L0 wakeup */
- pr_debug("received wakeup ap l2->l0\n");
drv->hostwake = 1;
wake_up_interruptible(&drv->bb_wait);
@@ -621,26 +626,24 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int value)
spin_unlock(&xmm_lock);
} else {
pr_debug("%s - rising\n", __func__);
+ spin_lock(&xmm_lock);
+ modem_acked_resume = true;
value = gpio_get_value(data->modem.xmm.ipc_hsic_active);
if (!value) {
pr_info("host active low: ignore request\n");
ipc_ap_wake_state = IPC_AP_WAKE_H;
+ spin_unlock(&xmm_lock);
return IRQ_HANDLED;
}
- value = gpio_get_value(data->modem.xmm.ipc_bb_wake);
- if (value) {
- /* Clear the slave wakeup request */
- gpio_set_value(data->modem.xmm.ipc_bb_wake, 0);
- pr_debug("gpio slave wakeup done ->\n");
- }
+
if (reenable_autosuspend && usbdev) {
reenable_autosuspend = false;
queue_work(workqueue, &autopm_resume_work);
}
modem_sleep_flag = false;
- baseband_xmm_set_power_status(BBXMM_PS_L0);
/* save gpio state */
ipc_ap_wake_state = IPC_AP_WAKE_H;
+ spin_unlock(&xmm_lock);
}
return IRQ_HANDLED;
}
@@ -774,6 +777,7 @@ static void xmm_power_work_func(struct work_struct *work)
pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n");
pr_debug("%s: ipc_hsic_active -> 0\n", __func__);
gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
+ modem_acked_resume = true;
/* reset / power on sequence */
xmm_power_reset_on(pdata);
/* set power status as on */
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index 25f737f75338..a85c2dccd1a3 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -799,6 +799,14 @@ static void enterprise_usb_hsic_preresume(void)
#endif
}
+static void enterprise_usb_hsic_post_resume(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef CONFIG_TEGRA_BB_XMM_POWER
+ baseband_xmm_set_power_status(BBXMM_PS_L0);
+#endif
+}
+
static void enterprise_usb_hsic_phy_power(void)
{
pr_debug("%s\n", __func__);
@@ -819,7 +827,7 @@ static struct tegra_usb_phy_platform_ops hsic_xmm_plat_ops = {
.post_suspend = enterprise_usb_hsic_postsupend,
.pre_resume = enterprise_usb_hsic_preresume,
.port_power = enterprise_usb_hsic_phy_power,
- .post_phy_on = enterprise_usb_hsic_phy_power,
+ .post_resume = enterprise_usb_hsic_post_resume,
.post_phy_off = enterprise_usb_hsic_post_phy_off,
};