From e7a7520c6494c6610835bd6e5c83e790a05892eb Mon Sep 17 00:00:00 2001 From: Vinayak Pane Date: Tue, 24 Jul 2012 21:13:56 -0700 Subject: arm: tegra: xmm: repair ipc_ap_wake_state at reset Preparing strict checking for ipc_ap_wake_state during modem initialization. Modify the flashless xmm wake irq part to avoid mixing with flashed modem irq handler. Remove unused init1 workqueue from the driver. Bug 1003141 Change-Id: I7b06b1783a140c0cc5121478e4983fab39862d7c Signed-off-by: Vinayak Pane Reviewed-on: http://git-master/r/118475 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Steve Lin --- arch/arm/mach-tegra/baseband-xmm-power.c | 111 ++++++++++--------------------- 1 file changed, 36 insertions(+), 75 deletions(-) (limited to 'arch/arm/mach-tegra/baseband-xmm-power.c') diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 9513bdc5d45f..cc330c86c581 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -77,18 +77,9 @@ static struct gpio tegra_baseband_gpios[] = { { -1, GPIOF_IN, "IPC_HSIC_SUS_REQ" }, }; -static enum { - IPC_AP_WAKE_UNINIT, - IPC_AP_WAKE_IRQ_READY, - IPC_AP_WAKE_INIT1, - IPC_AP_WAKE_INIT2, - IPC_AP_WAKE_L, - IPC_AP_WAKE_H, -} ipc_ap_wake_state; - static enum baseband_xmm_powerstate_t baseband_xmm_powerstate; +static enum ipc_ap_wake_state_t ipc_ap_wake_state; static struct workqueue_struct *workqueue; -static struct work_struct init1_work; static struct work_struct init2_work; static struct work_struct L2_resume_work; static struct work_struct autopm_resume_work; @@ -256,7 +247,6 @@ static int xmm_power_on(struct platform_device *device) /* reset the state machine */ baseband_xmm_powerstate = BBXMM_PS_INIT; modem_sleep_flag = false; - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; pr_debug("%s wake_st(%d) modem version %lu\n", __func__, ipc_ap_wake_state, modem_ver); @@ -264,6 +254,8 @@ static int xmm_power_on(struct platform_device *device) /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); + + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", @@ -291,7 +283,7 @@ static int xmm_power_on(struct platform_device *device) pr_debug("%s: reset flash modem\n", __func__); modem_power_on = false; - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); xmm_power_reset_on(pdata); @@ -552,41 +544,11 @@ void baseband_xmm_set_power_status(unsigned int status) } EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); -irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) + +irqreturn_t xmm_power_ipc_ap_wake_irq(int value) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; struct xmm_power_data *drv = &xmm_power_drv_data; - int value; - - value = gpio_get_value(data->modem.xmm.ipc_ap_wake); - pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - - /* modem initialization/bootup part*/ - if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { - pr_err("%s - spurious irq\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { - if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - got falling edge\n", __func__); - /* go to IPC_AP_WAKE_INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; - queue_work(workqueue, &init1_work); - } else - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - wait for falling edge\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { - if (!value) { - pr_debug("%s - got falling edge at INIT1\n", __func__); - /* go to IPC_AP_WAKE_INIT2 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; - queue_work(workqueue, &init2_work); - } else - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - got rising edge\n", __func__); - return IRQ_HANDLED; - } /* modem wakeup part */ if (!value) { @@ -646,41 +608,41 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_H; } - return IRQ_HANDLED; } EXPORT_SYMBOL(xmm_power_ipc_ap_wake_irq); -static void xmm_power_init1_work(struct work_struct *work) +static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) { - struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata; + struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value; - pr_debug("%s {\n", __func__); - - /* check if IPC_HSIC_ACTIVE high */ - value = gpio_get_value(pdata->modem.xmm.ipc_hsic_active); - if (value != 1) { - pr_err("%s - expected IPC_HSIC_ACTIVE high!\n", __func__); - return; - } - - /* wait 100 ms */ - msleep(100); - - /* set IPC_HSIC_ACTIVE low */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); - - /* wait 10 ms */ - usleep_range(10000, 11000); - - /* set IPC_HSIC_ACTIVE high */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1); + value = gpio_get_value(data->modem.xmm.ipc_ap_wake); + pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - /* wait 20 ms */ - msleep(20); + /* modem wakeup part */ + if (likely(ipc_ap_wake_state >= IPC_AP_WAKE_INIT2)) + return xmm_power_ipc_ap_wake_irq(value); - pr_debug("%s }\n", __func__); + /* modem initialization/bootup part*/ + if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { + pr_err("%s - spurious irq\n", __func__); + } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { + if (value) { + /* make state ready for falling edge */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s - got rising edge\n", __func__); + } + } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { + if (!value) { + pr_debug("%s - got falling edge at INIT1\n", __func__); + /* go to IPC_AP_WAKE_INIT2 state */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + queue_work(workqueue, &init2_work); + } else + pr_debug("%s - unexpected rising edge\n", __func__); + } + return IRQ_HANDLED; } static void xmm_power_init2_work(struct work_struct *work) @@ -960,7 +922,7 @@ static int xmm_power_driver_probe(struct platform_device *device) ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; err = request_threaded_irq( gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), - NULL, xmm_power_ipc_ap_wake_irq, + NULL, ipc_ap_wake_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "IPC_AP_WAKE_IRQ", NULL); if (err < 0) { @@ -973,9 +935,9 @@ static int xmm_power_driver_probe(struct platform_device *device) if (err < 0) pr_err("%s: enable_irq_wake error\n", __func__); - pr_debug("%s: AP_WAKE_INIT1\n", __func__); - /* ver 1130 or later starts in INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s: set state IPC_AP_WAKE_IRQ_READY\n", __func__); + /* ver 1130 or later start in IRQ_READY state */ + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; } /* init work queue */ @@ -990,7 +952,6 @@ static int xmm_power_driver_probe(struct platform_device *device) queue_work(workqueue, &xmm_power_drv_data.work); /* 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(&autopm_resume_work, xmm_power_autopm_resume); -- cgit v1.2.3