diff options
author | Michael Hsu <mhsu@nvidia.com> | 2011-10-14 17:26:07 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:52:39 -0800 |
commit | 645f91c68b19172da28779e86c2d60045fc64705 (patch) | |
tree | bc570f012238e1578d528f004048a477ad361a92 /arch/arm/mach-tegra/baseband-xmm-power2.c | |
parent | 7a6f2363adc93e15bc2b1f96a3b4db9d75a43552 (diff) |
arm: tegra: comms: GPIO changes for XMM modem ver 1130 or later
XMM modem version 1130 (or later) changes the GPIO power up
sequence. Add module variable to support pre-1130 and post-1130
modem versions.
BUG 828389
Reviewed-on: http://git-master/r/58240
(cherry picked from commit 0639c200face90d6dd0144acc7362c02909fa66c)
Change-Id: If3a3486741d72d1251deeca3759af6b39c2031f1
Reviewed-on: http://git-master/r/62750
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Rebase-Id: Rf848b30671a8739c11a376011165db6165f0a259
Diffstat (limited to 'arch/arm/mach-tegra/baseband-xmm-power2.c')
-rw-r--r-- | arch/arm/mach-tegra/baseband-xmm-power2.c | 540 |
1 files changed, 444 insertions, 96 deletions
diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c index 9601ed49e6a1..acb2ac344266 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power2.c +++ b/arch/arm/mach-tegra/baseband-xmm-power2.c @@ -22,6 +22,7 @@ #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/workqueue.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/fs.h> #include <linux/uaccess.h> @@ -32,15 +33,24 @@ MODULE_LICENSE("GPL"); -static struct baseband_power_platform_data *baseband_power2_driver_data; +static unsigned long XYZ = 500 * 1000000 + 30 * 1000 + 50; + +module_param(modem_ver, ulong, 0644); +MODULE_PARM_DESC(modem_ver, + "baseband xmm power2 - modem software version"); +module_param(modem_flash, ulong, 0644); +MODULE_PARM_DESC(modem_flash, + "baseband xmm power2 - modem flash (1 = flash, 0 = flashless)"); +module_param(modem_pm, ulong, 0644); +MODULE_PARM_DESC(modem_pm, + "baseband xmm power2 - modem power management (1 = pm, 0 = no pm)"); +module_param(XYZ, ulong, 0644); +MODULE_PARM_DESC(XYZ, + "baseband xmm power2 - timing parameters X/Y/Z delay in ms"); -static enum { - IPC_HSIC_SUS_REQ_UNINIT, - IPC_HSIC_SUS_REQ_IRQ_READY, - IPC_HSIC_SUS_REQ_INIT, - IPC_HSIC_SUS_REQ_L, - IPC_HSIC_SUS_REQ_H, -} ipc_hsic_sus_req_state; +static struct baseband_power_platform_data *baseband_power2_driver_data; +static struct workqueue_struct *workqueue; +static struct baseband_xmm_power_work_t *baseband_xmm_power2_work; static enum { IPC_AP_WAKE_UNINIT, @@ -51,11 +61,8 @@ static enum { IPC_AP_WAKE_H, } ipc_ap_wake_state; -static struct workqueue_struct *workqueue; -static struct work_struct init1_work; -static struct work_struct init2_work; - -static irqreturn_t ipc_hsic_sus_req_irq(int irq, void *dev_id) +static irqreturn_t baseband_xmm_power2_ver_lt_1130_ipc_ap_wake_irq2 + (int irq, void *dev_id) { int value; @@ -65,25 +72,65 @@ static irqreturn_t ipc_hsic_sus_req_irq(int irq, void *dev_id) if (!baseband_power2_driver_data) return IRQ_HANDLED; - /* IPC_HSIC_SUS_REQ state machine */ - if (ipc_hsic_sus_req_state < IPC_HSIC_SUS_REQ_IRQ_READY) { + /* IPC_AP_WAKE state machine */ + if (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) { + value = gpio_get_value(baseband_power2_driver_data-> + modem.xmm.ipc_ap_wake); + 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 */ + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + } else { + pr_debug("%s - IPC_AP_WAKE_INIT1" + " - wait for falling edge\n", + __func__); + } + } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { + value = gpio_get_value(baseband_power2_driver_data-> + modem.xmm.ipc_ap_wake); + if (!value) { + pr_debug("%s - IPC_AP_WAKE_INIT2" + " - wait for rising edge\n", + __func__); + } else { + pr_debug("%s - IPC_AP_WAKE_INIT2" + " - got rising edge\n", + __func__); + /* go to IPC_AP_WAKE_INIT2 state */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + /* queue work */ + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + } } else { value = gpio_get_value(baseband_power2_driver_data-> - modem.xmm.ipc_hsic_sus_req); + modem.xmm.ipc_ap_wake); if (!value) { pr_debug("%s - falling\n", __func__); - ipc_hsic_sus_req_state = IPC_HSIC_SUS_REQ_L; + ipc_ap_wake_state = IPC_AP_WAKE_L; } else { pr_debug("%s - rising\n", __func__); - ipc_hsic_sus_req_state = IPC_HSIC_SUS_REQ_H; + ipc_ap_wake_state = IPC_AP_WAKE_H; } + return baseband_xmm_power_ipc_ap_wake_irq(irq, dev_id); } return IRQ_HANDLED; } -static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) +static irqreturn_t baseband_xmm_power2_ver_ge_1130_ipc_ap_wake_irq2 + (int irq, void *dev_id) { int value; @@ -100,29 +147,20 @@ static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) value = gpio_get_value(baseband_power2_driver_data-> modem.xmm.ipc_ap_wake); 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 */ - queue_work(workqueue, &init1_work); - } else { - pr_debug("%s - IPC_AP_WAKE_INIT1 - wait for falling edge\n", - __func__); - } - } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { - value = gpio_get_value(baseband_power2_driver_data-> - modem.xmm.ipc_ap_wake); - if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT2 - wait for rising edge\n", - __func__); - } else { - pr_debug("%s - IPC_AP_WAKE_INIT2 - got rising edge\n", + pr_debug("%s - IPC_AP_WAKE_INIT1" + " - got falling edge\n", __func__); /* go to IPC_AP_WAKE_INIT2 state */ ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* queue work */ - queue_work(workqueue, &init2_work); + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + } else { + pr_debug("%s - IPC_AP_WAKE_INIT1" + " - wait for falling edge\n", + __func__); } } else { value = gpio_get_value(baseband_power2_driver_data-> @@ -134,12 +172,14 @@ static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) pr_debug("%s - rising\n", __func__); ipc_ap_wake_state = IPC_AP_WAKE_H; } + return baseband_xmm_power_ipc_ap_wake_irq(irq, dev_id); } return IRQ_HANDLED; } -static void baseband_xmm_power2_init1_work(struct work_struct *work) +static void baseband_xmm_power2_flashless_pm_ver_lt_1130_step1 + (struct work_struct *work) { int value; @@ -167,7 +207,8 @@ static void baseband_xmm_power2_init1_work(struct work_struct *work) pr_debug("%s }\n", __func__); } -static void baseband_xmm_power2_init2_work(struct work_struct *work) +static void baseband_xmm_power2_flashless_pm_ver_lt_1130_step2 + (struct work_struct *work) { int value; @@ -194,8 +235,8 @@ static void baseband_xmm_power2_init2_work(struct work_struct *work) struct file *filp; oldfs = get_fs(); set_fs(KERNEL_DS); - filp = filp_open("/sys/devices/platform/tegra-ehci.1/ehci_power", O_RDWR, 0); - if (!filp) { + filp = filp_open(TEGRA_EHCI_DEVICE, O_RDWR, 0); + if (IS_ERR(filp) || (filp == NULL)) { pr_err("open ehci_power failed\n"); } else { filp->f_op->write(filp, "1", 1, &filp->f_pos); @@ -225,69 +266,381 @@ static void baseband_xmm_power2_init2_work(struct work_struct *work) pr_debug("%s }\n", __func__); } +static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step1 + (struct work_struct *work) +{ + int X = XYZ / 1000000; + int Y = XYZ / 1000 - X * 1000; + int Z = XYZ % 1000; + + pr_info("%s {\n", __func__); + + pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z); + + /* check for platform data */ + if (!baseband_power2_driver_data) + return; + + /* turn off usb host controller */ + { + mm_segment_t oldfs; + struct file *filp; + oldfs = get_fs(); + set_fs(KERNEL_DS); + filp = filp_open(TEGRA_EHCI_DEVICE, O_RDWR, 0); + if (IS_ERR(filp) || (filp == NULL)) { + pr_err("open ehci_power failed\n"); + } else { + filp->f_op->write(filp, "0", 1, &filp->f_pos); + filp_close(filp, NULL); + } + set_fs(oldfs); + } + + /* wait X ms */ + mdelay(X); + + /* set IPC_HSIC_ACTIVE low */ + gpio_set_value(baseband_power2_driver_data-> + modem.xmm.ipc_hsic_active, 0); + + pr_info("%s }\n", __func__); +} + +static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step2 + (struct work_struct *work) +{ + int X = XYZ / 1000000; + int Y = XYZ / 1000 - X * 1000; + int Z = XYZ % 1000; + + pr_info("%s {\n", __func__); + + pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z); + + /* check for platform data */ + if (!baseband_power2_driver_data) + return; + + /* wait Y ms */ + mdelay(Y); + + /* turn on usb host controller */ + { + mm_segment_t oldfs; + struct file *filp; + oldfs = get_fs(); + set_fs(KERNEL_DS); + filp = filp_open(TEGRA_EHCI_DEVICE, O_RDWR, 0); + if (IS_ERR(filp) || (filp == NULL)) { + pr_err("open ehci_power failed\n"); + } else { + filp->f_op->write(filp, "1", 1, &filp->f_pos); + filp_close(filp, NULL); + } + set_fs(oldfs); + } + + /* wait Z ms */ + mdelay(Z); + + /* set IPC_HSIC_ACTIVE high */ + gpio_set_value(baseband_power2_driver_data-> + modem.xmm.ipc_hsic_active, 1); + + /* queue work function to check if enumeration succeeded */ + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + + pr_info("%s }\n", __func__); +} + +static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step3 + (struct work_struct *work) +{ + int X = XYZ / 1000000; + int Y = XYZ / 1000 - X * 1000; + int Z = XYZ % 1000; + int enum_success = 0; + + pr_info("%s {\n", __func__); + + pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z); + + /* check for platform data */ + if (!baseband_power2_driver_data) + return; + + /* wait 500 ms */ + mdelay(500); + + /* check if enumeration succeeded */ + { + mm_segment_t oldfs; + struct file *filp; + oldfs = get_fs(); + set_fs(KERNEL_DS); + filp = filp_open("/sys/bus/usb/devices/usb2/2-1/manufacturer", + O_RDONLY, 0); + if (IS_ERR(filp) || (filp == NULL)) { + pr_err("open /sys/bus/usb/devices" + "/usb2/2-1/manufacturer failed %ld\n", + PTR_ERR(filp)); + } else { + filp_close(filp, NULL); + enum_success = 1; + } + set_fs(oldfs); + } + + /* if enumeration failed, attempt recovery pulse */ + if (!enum_success) { + pr_info("attempting recovery pulse...\n"); + /* wait 20 ms */ + mdelay(20); + /* set IPC_HSIC_ACTIVE low */ + gpio_set_value(baseband_power2_driver_data-> + modem.xmm.ipc_hsic_active, 0); + /* wait 20 ms */ + mdelay(20); + /* set IPC_HSIC_ACTIVE high */ + gpio_set_value(baseband_power2_driver_data-> + modem.xmm.ipc_hsic_active, 1); + /* check if recovery pulse worked */ + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + } + + pr_info("%s }\n", __func__); +} + +static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step4 + (struct work_struct *work) +{ + int X = XYZ / 1000000; + int Y = XYZ / 1000 - X * 1000; + int Z = XYZ % 1000; + int enum_success = 0; + + pr_info("%s {\n", __func__); + + pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z); + + /* check for platform data */ + if (!baseband_power2_driver_data) + return; + + /* wait 500 ms */ + mdelay(500); + + /* check if enumeration succeeded */ + { + mm_segment_t oldfs; + struct file *filp; + oldfs = get_fs(); + set_fs(KERNEL_DS); + filp = filp_open("/sys/bus/usb/devices/usb2/2-1/manufacturer", + O_RDONLY, 0); + if (IS_ERR(filp) || (filp == NULL)) { + pr_err("open /sys/bus/usb/devices" + "/usb2/2-1/manufacturer failed %ld\n", + PTR_ERR(filp)); + } else { + filp_close(filp, NULL); + enum_success = 1; + } + set_fs(oldfs); + } + + /* if recovery pulse did not fix enumeration, retry from beginning */ + if (!enum_success) { + static int retry = 3; + if (!retry) { + pr_info("failed to enumerate modem software" + " - too many retry attempts\n"); + } else { + pr_info("recovery pulse failed to fix modem" + " enumeration..." + " restarting from beginning" + " - attempt #%d\n", + retry); + --retry; + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; + baseband_xmm_power2_work->state = + BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1; + queue_work(workqueue, (struct work_struct *) + baseband_xmm_power2_work); + } + } + + pr_info("%s }\n", __func__); +} + +static int free_ipc_ap_wake_irq; + +static void baseband_xmm_power2_work_func(struct work_struct *work) +{ + struct baseband_xmm_power_work_t *bbxmm_work + = (struct baseband_xmm_power_work_t *) work; + int err; + + pr_debug("%s\n", __func__); + + switch (bbxmm_work->state) { + case BBXMM_WORK_UNINIT: + pr_debug("BBXMM_WORK_UNINIT\n"); + /* free baseband irq(s) */ + if (free_ipc_ap_wake_irq) { + free_irq(gpio_to_irq(baseband_power2_driver_data + ->modem.xmm.ipc_ap_wake), NULL); + free_ipc_ap_wake_irq = 0; + } + break; + case BBXMM_WORK_INIT: + pr_debug("BBXMM_WORK_INIT\n"); + /* request baseband irq(s) */ + ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; + err = request_irq(gpio_to_irq(baseband_power2_driver_data + ->modem.xmm.ipc_ap_wake), + (modem_ver < XMM_MODEM_VER_1130) + ? baseband_xmm_power2_ver_lt_1130_ipc_ap_wake_irq2 + : baseband_xmm_power2_ver_ge_1130_ipc_ap_wake_irq2, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "BBXMM_POWER2_IPC_AP_WAKE_IRQ", + NULL); + if (err < 0) { + pr_err("%s - request irq IPC_AP_WAKE_IRQ failed\n", + __func__); + return; + } + free_ipc_ap_wake_irq = 1; + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; + /* go to next state */ + bbxmm_work->state = (modem_flash && !modem_pm) + ? BBXMM_WORK_INIT_FLASH_STEP1 + : (modem_flash && modem_pm) + ? BBXMM_WORK_INIT_FLASH_PM_STEP1 + : (!modem_flash && modem_pm) + ? BBXMM_WORK_INIT_FLASHLESS_PM_STEP1 + : BBXMM_WORK_UNINIT; + queue_work(workqueue, work); + break; + case BBXMM_WORK_INIT_FLASH_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASH_STEP1\n"); + break; + case BBXMM_WORK_INIT_FLASH_PM_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n"); + /* go to next state */ + bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130) + ? BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1 + : BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1; + queue_work(workqueue, work); + break; + case BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1\n"); + break; + case BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1\n"); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n"); + /* go to next state */ + bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130) + ? BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ + : BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1; + queue_work(workqueue, work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ" + " - waiting for IPC_AP_WAKE_IRQ to trigger step1\n"); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1\n"); + baseband_xmm_power2_flashless_pm_ver_lt_1130_step1(work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2\n"); + baseband_xmm_power2_flashless_pm_ver_lt_1130_step2(work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1\n"); + baseband_xmm_power2_flashless_pm_ver_ge_1130_step1(work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2\n"); + baseband_xmm_power2_flashless_pm_ver_ge_1130_step2(work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3\n"); + baseband_xmm_power2_flashless_pm_ver_ge_1130_step3(work); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4\n"); + baseband_xmm_power2_flashless_pm_ver_ge_1130_step4(work); + break; + } + +} + static int baseband_xmm_power2_driver_probe(struct platform_device *device) { struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; - int err; + = (struct baseband_power_platform_data *) + device->dev.platform_data; pr_debug("%s\n", __func__); /* save platform data */ baseband_power2_driver_data = data; - /* request baseband irq(s) */ - ipc_hsic_sus_req_state = IPC_HSIC_SUS_REQ_UNINIT; - err = request_irq(gpio_to_irq(data->modem.xmm.ipc_hsic_sus_req), - ipc_hsic_sus_req_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "IPC_HSIC_SUS_REQ_IRQ", - NULL); - if (err < 0) { - pr_err("%s - request irq IPC_HSIC_SUS_REQ_IRQ failed\n", - __func__); - return err; - } - ipc_hsic_sus_req_state = IPC_HSIC_SUS_REQ_IRQ_READY; - ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; - err = request_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake), - ipc_ap_wake_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "IPC_AP_WAKE_IRQ", - NULL); - if (err < 0) { - pr_err("%s - request irq IPC_AP_WAKE_IRQ failed\n", - __func__); - return err; - } - ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; - /* init work queue */ workqueue = create_singlethread_workqueue - ("baseband_power_workqueue"); + ("baseband_xmm_power2_workqueue"); if (!workqueue) { pr_err("cannot create workqueue\n"); return -1; } - INIT_WORK(&init1_work, baseband_xmm_power2_init1_work); - INIT_WORK(&init2_work, baseband_xmm_power2_init2_work); + baseband_xmm_power2_work = (struct baseband_xmm_power_work_t *) + kmalloc(sizeof(struct baseband_xmm_power_work_t), GFP_KERNEL); + if (!baseband_xmm_power2_work) { + pr_err("cannot allocate baseband_xmm_power2_work\n"); + return -1; + } + INIT_WORK((struct work_struct *) baseband_xmm_power2_work, + baseband_xmm_power2_work_func); + baseband_xmm_power2_work->state = BBXMM_WORK_INIT; + queue_work(workqueue, + (struct work_struct *) baseband_xmm_power2_work); return 0; } static int baseband_xmm_power2_driver_remove(struct platform_device *device) { + struct baseband_power_platform_data *data + = (struct baseband_power_platform_data *) + device->dev.platform_data; + pr_debug("%s\n", __func__); /* check for platform data */ - if (!baseband_power2_driver_data) + if (!data) return 0; - /* free baseband irq(s) */ - free_irq(gpio_to_irq(baseband_power2_driver_data - ->modem.xmm.ipc_ap_wake), NULL); - free_irq(gpio_to_irq(baseband_power2_driver_data - ->modem.xmm.ipc_hsic_sus_req), NULL); + /* free irq */ + if (free_ipc_ap_wake_irq) { + free_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake), NULL); + free_ipc_ap_wake_irq = 0; + } + + /* free work structure */ + destroy_workqueue(workqueue); + kfree(baseband_xmm_power2_work); + baseband_xmm_power2_work = (struct baseband_xmm_power_work_t *) 0; return 0; } @@ -296,35 +649,31 @@ static int baseband_xmm_power2_driver_remove(struct platform_device *device) static int baseband_xmm_power2_driver_suspend(struct platform_device *device, pm_message_t state) { - pr_debug("%s\n", __func__); + struct baseband_power_platform_data *data + = (struct baseband_power_platform_data *) + device->dev.platform_data; + + pr_debug("%s - nop\n", __func__); /* check for platform data */ - if (!baseband_power2_driver_data) + if (!data) return 0; - /* signal bb to suspend hsic */ - gpio_set_value(baseband_power2_driver_data - ->modem.xmm.ipc_hsic_active, 0); - return 0; } static int baseband_xmm_power2_driver_resume(struct platform_device *device) { - pr_debug("%s\n", __func__); + struct baseband_power_platform_data *data + = (struct baseband_power_platform_data *) + device->dev.platform_data; + + pr_debug("%s - nop\n", __func__); /* check for platform data */ - if (!baseband_power2_driver_data) + if (!data) return 0; - /* wake bb */ - gpio_set_value(baseband_power2_driver_data - ->modem.xmm.ipc_bb_wake, 1); - - /* signal bb to resume hsic */ - gpio_set_value(baseband_power2_driver_data - ->modem.xmm.ipc_hsic_active, 1); - return 0; } #endif @@ -355,4 +704,3 @@ static void __exit baseband_xmm_power2_exit(void) module_init(baseband_xmm_power2_init) module_exit(baseband_xmm_power2_exit) - |