From e96e462aee43ed8699f5cd64728c389e92ef402e Mon Sep 17 00:00:00 2001 From: Vinayak Pane Date: Thu, 23 Aug 2012 19:48:12 -0700 Subject: 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 Reviewed-on: http://git-master/r/129533 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/baseband-xmm-power.c | 92 +++++++++++++++++--------------- arch/arm/mach-tegra/board-enterprise.c | 10 +++- 2 files changed, 57 insertions(+), 45 deletions(-) (limited to 'arch') 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, }; -- cgit v1.2.3