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-power.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-power.c')
-rw-r--r-- | arch/arm/mach-tegra/baseband-xmm-power.c | 484 |
1 files changed, 330 insertions, 154 deletions
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index dc8f8191a95d..fc4e957c964e 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.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,34 @@ #include "gpio-names.h" #include "baseband-xmm-power.h" +#define VENDOR_ID 0x1519 +#define PRODUCT_ID 0x0020 + MODULE_LICENSE("GPL"); -unsigned long enum_delay_ms = 1000; +unsigned long modem_ver = XMM_MODEM_VER_1121; +EXPORT_SYMBOL(modem_ver); -module_param(enum_delay_ms, ulong, 0644); -MODULE_PARM_DESC(enum_delay_ms, "baseband xmm power" - " - delay in ms between modem on and enumeration"); +unsigned long modem_flash; +EXPORT_SYMBOL(modem_flash); + +unsigned long modem_pm = 1; +EXPORT_SYMBOL(modem_pm); -#define TEGRA_EHCI_DEVICE "/sys/devices/platform/tegra-ehci.1/ehci_power" +unsigned long enum_delay_ms = 1000; /* ignored if !modem_flash */ + +module_param(modem_ver, ulong, 0644); +MODULE_PARM_DESC(modem_ver, + "baseband xmm power - modem software version"); +module_param(modem_flash, ulong, 0644); +MODULE_PARM_DESC(modem_flash, + "baseband xmm power - modem flash (1 = flash, 0 = flashless)"); +module_param(modem_pm, ulong, 0644); +MODULE_PARM_DESC(modem_pm, + "baseband xmm power - modem power management (1 = pm, 0 = no pm)"); +module_param(enum_delay_ms, ulong, 0644); +MODULE_PARM_DESC(enum_delay_ms, + "baseband xmm power - delay in ms between modem on and enumeration"); /* Currently no baseband initiated suspend */ #define BB_INITIATED_L2_SUSPEND 0 @@ -73,6 +93,8 @@ static enum { IPC_AP_WAKE_H, } ipc_ap_wake_state; +enum baseband_xmm_powerstate_t baseband_xmm_powerstate; + static struct workqueue_struct *workqueue; static struct work_struct init1_work; static struct work_struct init2_work; @@ -81,59 +103,54 @@ static struct baseband_power_platform_data *baseband_power_driver_data; static bool register_hsic_device; static struct wake_lock wakelock; -/* static functions */ -static int baseband_xmm_power_on(struct platform_device *device); -static int baseband_xmm_power_off(struct platform_device *device); - -static ssize_t baseband_xmm_onoff(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int power_onoff; - struct platform_device *device = to_platform_device(dev); - - pr_debug("%s\n", __func__); - - if (sscanf(buf, "%d", &power_onoff) != 1) - return -EINVAL; - - if (power_onoff == 0) - baseband_xmm_power_off(device); - else if (power_onoff == 1) - baseband_xmm_power_on(device); - return count; -} - -static DEVICE_ATTR(xmm_onoff, S_IRUSR | S_IWUSR | S_IRGRP, - NULL, baseband_xmm_onoff); - static int baseband_xmm_power_on(struct platform_device *device) { - int value; - struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; + struct baseband_power_platform_data *data; - pr_debug("%s{\n", __func__); + pr_debug("%s {\n", __func__); - /* check for platform data */ - if (!baseband_power_driver_data) + /* check for device / platform data */ + if (!device) { + pr_err("%s: !device\n", __func__); return -EINVAL; - - /* check if IPC_HSIC_ACTIVE low */ - value = gpio_get_value(baseband_power_driver_data-> - modem.xmm.ipc_hsic_active); - if (value != 0) { - pr_err("%s - expected IPC_HSIC_ACTIVE low!\n", __func__); + } + data = (struct baseband_power_platform_data *) + device->dev.platform_data; + if (!data) { + pr_err("%s: !data\n", __func__); return -EINVAL; } + /* turn on usb host controller */ + if (!modem_flash) { + /* if already registered usb host controller, then turn on + * using ehci_power file + */ + if (!register_hsic_device) { + mm_segment_t oldfs; + struct file *filp; + pr_debug("%s(%d) register usb host controller echo on\n", + __func__, __LINE__); + 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); + } + /* else if usb host controller not registered yet, then turn + * on will occur later in this function (when usb host + * controller is registered for first time) + */ + } + /* reset the state machine */ baseband_xmm_powerstate = BBXMM_PS_INIT; - ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; - - /* set IPC_HSIC_ACTIVE high */ - gpio_set_value(baseband_power_driver_data-> - modem.xmm.ipc_hsic_active, 1); + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* wait 20 ms */ mdelay(20); @@ -146,23 +163,15 @@ static int baseband_xmm_power_on(struct platform_device *device) udelay(40); gpio_set_value(data->modem.xmm.bb_on, 0); - if (enum_delay_ms) - mdelay(enum_delay_ms); - - /* 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 (!filp) { - pr_err("open ehci_power failed\n"); - } else { - filp->f_op->write(filp, "1", 1, &filp->f_pos); - filp_close(filp, NULL); + /* register usb host controller */ + if (!modem_flash) { + /* register usb host controller only once */ + if (register_hsic_device) { + pr_debug("%s(%d) register usb host controller\n", + __func__, __LINE__); + platform_device_register(data->modem.xmm.hsic_device); + register_hsic_device = false; } - set_fs(oldfs); } pr_debug("%s }\n", __func__); @@ -172,10 +181,21 @@ static int baseband_xmm_power_on(struct platform_device *device) static int baseband_xmm_power_off(struct platform_device *device) { - struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; + struct baseband_power_platform_data *data; - pr_debug("%s\n", __func__); + pr_debug("%s {\n", __func__); + + /* check for device / platform data */ + if (!device) { + pr_err("%s: !device\n", __func__); + return -EINVAL; + } + data = (struct baseband_power_platform_data *) + device->dev.platform_data; + if (!data) { + pr_err("%s: !data\n", __func__); + return -EINVAL; + } /* turn off usb host controller */ { @@ -184,7 +204,7 @@ static int baseband_xmm_power_off(struct platform_device *device) oldfs = get_fs(); set_fs(KERNEL_DS); filp = filp_open(TEGRA_EHCI_DEVICE, O_RDWR, 0); - if (!filp) { + if (IS_ERR(filp) || (filp == NULL)) { pr_err("open ehci_power failed\n"); } else { filp->f_op->write(filp, "0", 1, &filp->f_pos); @@ -196,6 +216,7 @@ static int baseband_xmm_power_off(struct platform_device *device) /* set IPC_HSIC_ACTIVE low */ gpio_set_value(baseband_power_driver_data-> modem.xmm.ipc_hsic_active, 0); + /* wait 20 ms */ mdelay(20); @@ -203,24 +224,48 @@ static int baseband_xmm_power_off(struct platform_device *device) gpio_set_value(data->modem.xmm.bb_rst, 0); mdelay(1); + pr_debug("%s }\n", __func__); + return 0; } +static ssize_t baseband_xmm_onoff(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int power_onoff; + struct platform_device *device = to_platform_device(dev); + + pr_debug("%s\n", __func__); + + if (sscanf(buf, "%d", &power_onoff) != 1) + return -EINVAL; + + if (power_onoff == 0) + baseband_xmm_power_off(device); + else if (power_onoff == 1) + baseband_xmm_power_on(device); + return count; +} + +static DEVICE_ATTR(xmm_onoff, S_IRUSR | S_IWUSR | S_IRGRP, + NULL, baseband_xmm_onoff); + void baseband_xmm_set_power_status(unsigned int status) { switch (status) { case BBXMM_PS_L0: wake_lock(&wakelock); - break; + break; case BBXMM_PS_L2: wake_unlock(&wakelock); - break; + break; case BBXMM_PS_L2TOL0: /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) queue_work(workqueue, &init3_work); default: - break; + break; } baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); @@ -228,7 +273,8 @@ void baseband_xmm_set_power_status(unsigned int status) EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); #if BB_INITIATED_L2_SUSPEND -static irqreturn_t ipc_hsic_sus_req_irq(int irq, void *dev_id) +static irqreturn_t baseband_xmm_power_ipc_hsic_sus_req_irq + (int irq, void *dev_id) { int value; @@ -250,10 +296,9 @@ static irqreturn_t ipc_hsic_sus_req_irq(int irq, void *dev_id) return IRQ_HANDLED; } - #endif -static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) +irqreturn_t baseband_xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) { int value; @@ -265,24 +310,28 @@ static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) value = gpio_get_value(baseband_power_driver_data-> modem.xmm.ipc_ap_wake); if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT1 - got falling edge\n", + 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", + 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_power_driver_data-> modem.xmm.ipc_ap_wake); if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT2 - wait for rising edge\n", + 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_INIT2" + " - got rising edge\n", __func__); /* go to IPC_AP_WAKE_INIT2 state */ ipc_ap_wake_state = IPC_AP_WAKE_INIT2; @@ -294,21 +343,32 @@ static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) modem.xmm.ipc_ap_wake); if (!value) { pr_debug("%s - falling\n", __func__); - pr_debug("gpio host wakeup done <-\n"); - /* Set the slave wakeup request */ - gpio_set_value(baseband_power_driver_data-> - modem.xmm.ipc_bb_wake, 0); - pr_debug("gpio slave wakeup done ->\n"); + /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_L; - baseband_xmm_set_power_status(BBXMM_PS_L0); } else { pr_debug("%s - rising\n", __func__); + /* [ver >= 1130] gpio protocol rising edge */ + if (modem_ver >= XMM_MODEM_VER_1130) { + pr_debug("gpio host wakeup done <-\n"); + value = gpio_get_value + (baseband_power_driver_data-> + modem.xmm.ipc_bb_wake); + if (value) { + /* Clear the slave wakeup request */ + gpio_set_value + (baseband_power_driver_data-> + modem.xmm.ipc_bb_wake, 0); + pr_debug("gpio slave wakeup done ->\n"); + } + } + /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_H; } } return IRQ_HANDLED; } +EXPORT_SYMBOL(baseband_xmm_power_ipc_ap_wake_irq); static void baseband_xmm_power_init1_work(struct work_struct *work) { @@ -368,49 +428,162 @@ static void baseband_xmm_power_init3_work(struct work_struct *work) modem.xmm.ipc_bb_wake, 1); } +static void baseband_xmm_power_reset_on(void) +{ + /* reset / power on sequence */ + mdelay(40); + gpio_set_value(baseband_power_driver_data->modem.xmm.bb_rst, 1); + mdelay(1); + gpio_set_value(baseband_power_driver_data->modem.xmm.bb_on, 1); + udelay(40); + gpio_set_value(baseband_power_driver_data->modem.xmm.bb_on, 0); +} + +static struct baseband_xmm_power_work_t *baseband_xmm_power_work; + +static void baseband_xmm_power_work_func(struct work_struct *work) +{ + struct baseband_xmm_power_work_t *bbxmm_work + = (struct baseband_xmm_power_work_t *) work; + + pr_debug("%s\n", __func__); + + switch (bbxmm_work->state) { + case BBXMM_WORK_UNINIT: + pr_debug("BBXMM_WORK_UNINIT\n"); + break; + case BBXMM_WORK_INIT: + pr_debug("BBXMM_WORK_INIT\n"); + /* 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"); + /* register usb host controller */ + platform_device_register(baseband_power_driver_data->modem + .xmm.hsic_device); + break; + case BBXMM_WORK_INIT_FLASH_PM_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n"); + /* [modem ver >= 1130] start with IPC_HSIC_ACTIVE low */ + if (modem_ver >= XMM_MODEM_VER_1130) { + pr_debug("%s: ver > 1130:" + " ipc_hsic_active -> 0\n", __func__); + gpio_set_value(baseband_power_driver_data-> + modem.xmm.ipc_hsic_active, 0); + } + /* reset / power on sequence */ + baseband_xmm_power_reset_on(); + /* optional delay + * 0 = flashless + * ==> causes next step to enumerate modem boot rom + * (058b / 0041) + * some delay > boot rom timeout + * ==> causes next step to enumerate modem software + * (1519 / 0020) + * (requires modem to be flash version, not flashless + * version) + */ + if (enum_delay_ms) + mdelay(enum_delay_ms); + /* register usb host controller */ + platform_device_register(baseband_power_driver_data->modem + .xmm.hsic_device); + /* 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_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1\n"); + break; + case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1: + pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1\n"); + break; + default: + break; + } + +} + static int baseband_xmm_power_driver_probe(struct platform_device *device) { - struct device *dev = &device->dev; struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; + = (struct baseband_power_platform_data *) + device->dev.platform_data; + struct device *dev = &device->dev; int err; pr_debug("%s\n", __func__); - register_hsic_device = true; - baseband_xmm_powerstate = BBXMM_PS_UNINIT; + /* check for platform data */ + if (!data) + return -ENODEV; + /* check if supported modem */ if (data->baseband_type != BASEBAND_XMM) { pr_err("unsuppported modem\n"); return -ENODEV; } + /* save platform data */ + baseband_power_driver_data = data; + + /* create device file */ err = device_create_file(dev, &dev_attr_xmm_onoff); if (err < 0) { pr_err("%s - device_create_file failed\n", __func__); return -ENODEV; } - /* save platform data */ - baseband_power_driver_data = data; + /* init wake lock */ + wake_lock_init(&wakelock, WAKE_LOCK_SUSPEND, "baseband_xmm_power"); /* request baseband gpio(s) */ - tegra_baseband_gpios[0].gpio = data->modem.xmm.bb_rst; - tegra_baseband_gpios[1].gpio = data->modem.xmm.bb_on; - tegra_baseband_gpios[2].gpio = data->modem.xmm.ipc_bb_wake; - tegra_baseband_gpios[3].gpio = data->modem.xmm.ipc_ap_wake; - tegra_baseband_gpios[4].gpio = data->modem.xmm.ipc_hsic_active; - tegra_baseband_gpios[5].gpio = data->modem.xmm.ipc_hsic_sus_req; + tegra_baseband_gpios[0].gpio = baseband_power_driver_data + ->modem.xmm.bb_rst; + tegra_baseband_gpios[1].gpio = baseband_power_driver_data + ->modem.xmm.bb_on; + tegra_baseband_gpios[2].gpio = baseband_power_driver_data + ->modem.xmm.ipc_bb_wake; + tegra_baseband_gpios[3].gpio = baseband_power_driver_data + ->modem.xmm.ipc_ap_wake; + tegra_baseband_gpios[4].gpio = baseband_power_driver_data + ->modem.xmm.ipc_hsic_active; + tegra_baseband_gpios[5].gpio = baseband_power_driver_data + ->modem.xmm.ipc_hsic_sus_req; err = gpio_request_array(tegra_baseband_gpios, ARRAY_SIZE(tegra_baseband_gpios)); if (err < 0) { pr_err("%s - request gpio(s) failed\n", __func__); - return err; + return -ENODEV; } /* request baseband irq(s) */ #if BB_INITIATED_L2_SUSPEND - if (enum_delay_ms) { + if (modem_pm) { 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, @@ -425,10 +598,11 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device) ipc_hsic_sus_req_state = IPC_HSIC_SUS_REQ_IRQ_READY; } #endif - if (enum_delay_ms) { + if (modem_flash && modem_pm) { + pr_info("%s: request_irq IPC_AP_WAKE_IRQ\n", __func__); ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; err = request_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake), - ipc_ap_wake_irq, + baseband_xmm_power_ipc_ap_wake_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "IPC_AP_WAKE_IRQ", NULL); @@ -438,6 +612,11 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device) return err; } ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; + if (modem_ver >= XMM_MODEM_VER_1130) { + pr_debug("%s: ver > 1130: AP_WAKE_INIT1\n", __func__); + /* ver 1130 or later starts in INIT1 state */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + } } /* init work queue */ @@ -447,52 +626,56 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device) pr_err("cannot create workqueue\n"); return -1; } + baseband_xmm_power_work = (struct baseband_xmm_power_work_t *) + kmalloc(sizeof(struct baseband_xmm_power_work_t), GFP_KERNEL); + if (!baseband_xmm_power_work) { + pr_err("cannot allocate baseband_xmm_power_work\n"); + return -1; + } + INIT_WORK((struct work_struct *) baseband_xmm_power_work, + baseband_xmm_power_work_func); + baseband_xmm_power_work->state = BBXMM_WORK_INIT; + queue_work(workqueue, + (struct work_struct *) baseband_xmm_power_work); - wake_lock_init(&wakelock, WAKE_LOCK_SUSPEND, "baseband_xmm_power"); - - baseband_xmm_powerstate = BBXMM_PS_INIT; + /* init work objects */ INIT_WORK(&init1_work, baseband_xmm_power_init1_work); INIT_WORK(&init2_work, baseband_xmm_power_init2_work); INIT_WORK(&init3_work, baseband_xmm_power_init3_work); - /* reset / power on sequence */ - mdelay(40); - gpio_set_value(data->modem.xmm.bb_rst, 1); - mdelay(1); - gpio_set_value(data->modem.xmm.bb_on, 1); - udelay(40); - gpio_set_value(data->modem.xmm.bb_on, 0); - - /* optional delay - * 0 = flashless - * ==> causes next step to enumerate modem boot rom (058b / 0041) - * some delay > boot rom timeout - * ==> causes next step to enumerate modem software (1519 / 0020) - * (requires modem to be flash version, not flashless version) - */ - if (enum_delay_ms) - mdelay(enum_delay_ms); - - /* register usb host controller */ - if (!enum_delay_ms) - platform_device_register(data->modem.xmm.hsic_device); + /* init state variables */ + register_hsic_device = true; + baseband_xmm_powerstate = BBXMM_PS_UNINIT; return 0; } static int baseband_xmm_power_driver_remove(struct platform_device *device) { - struct device *dev = &device->dev; struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; + = (struct baseband_power_platform_data *) + device->dev.platform_data; + struct device *dev = &device->dev; pr_debug("%s\n", __func__); + /* check for platform data */ + if (!data) + return 0; + + /* free work structure */ + kfree(baseband_xmm_power_work); + baseband_xmm_power_work = (struct baseband_xmm_power_work_t *) 0; + /* free baseband irq(s) */ - if (enum_delay_ms) { - free_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake), NULL); + if (modem_flash && modem_pm) { + free_irq(gpio_to_irq(baseband_power_driver_data + ->modem.xmm.ipc_ap_wake), NULL); + } + if (modem_pm) { #if BB_INITIATED_L2_SUSPEND - free_irq(gpio_to_irq(data->modem.xmm.ipc_hsic_sus_req), NULL); + free_irq(gpio_to_irq(baseband_power_driver_data + ->modem.xmm.ipc_hsic_sus_req), NULL); #endif } @@ -500,9 +683,12 @@ static int baseband_xmm_power_driver_remove(struct platform_device *device) gpio_free_array(tegra_baseband_gpios, ARRAY_SIZE(tegra_baseband_gpios)); - device_remove_file(dev, &dev_attr_xmm_onoff); + /* destroy wake lock */ wake_lock_destroy(&wakelock); + /* delete device file */ + device_remove_file(dev, &dev_attr_xmm_onoff); + /* unregister usb host controller */ platform_device_unregister(baseband_power_driver_data-> modem.xmm.hsic_device); @@ -513,54 +699,44 @@ static int baseband_xmm_power_driver_remove(struct platform_device *device) static int baseband_xmm_power_driver_suspend(struct platform_device *device, pm_message_t state) { - struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; - pr_debug("%s\n", __func__); - - /* Indiate host active low to CP*/ - gpio_set_value(data->modem.xmm.ipc_hsic_active, 0); - pr_debug("gpio host active low->\n"); - - baseband_xmm_set_power_status(BBXMM_PS_L3); - return 0; } static int baseband_xmm_power_driver_resume(struct platform_device *device) { struct baseband_power_platform_data *data - = (struct baseband_power_platform_data *) device->dev.platform_data; + = (struct baseband_power_platform_data *) + device->dev.platform_data; int value; int delay = 10000; /* maxmum delay in msec */ pr_debug("%s\n", __func__); + /* check for platform data */ + if (!baseband_power_driver_data) + return 0; + + baseband_xmm_set_power_status(BBXMM_PS_L3TOL0); + value = gpio_get_value(data->modem.xmm.ipc_ap_wake); - if (!value) { - pr_info("AP Initiated L3 -> L0\n"); + if (value) { + pr_info("AP L3 -> L0\n"); /* wake bb */ gpio_set_value(data->modem.xmm.ipc_bb_wake, 1); - pr_debug("waiting for host wakeup\n"); + pr_debug("waiting for host wakeup...\n"); do { mdelay(1); value = gpio_get_value(data->modem.xmm.ipc_ap_wake); delay--; - } while ((!value) && (delay)); + } while ((value) && (delay)); if (delay) - pr_debug("gpio host wakeup high <-\n"); - else - pr_err("%s host wakeup not happened\n", __func__); + pr_debug("gpio host wakeup low <-\n"); } else { - pr_info("CP Initiated L3 -> L0\n"); + pr_info("CP L3 -> L0\n"); } - /* signal bb to resume hsic */ - gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); - - baseband_xmm_set_power_status(BBXMM_PS_L3TOL0); - return 0; } |