/* this function holds xmm_lock */ void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value = 0; unsigned long flags; if (baseband_xmm_get_power_status() == status) return; /* avoid prints inside spinlock */ if (status <= BBXMM_PS_L2) pr_info("%s\n", status == BBXMM_PS_L0 ? "L0" : "L2"); spin_lock_irqsave(&xmm_lock, flags); switch (status) { case BBXMM_PS_L0: 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); if (!value) { pr_debug("L0 gpio set ipc_hsic_active=1 ->\n"); gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); } if (modem_power_on) { 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: 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"); system_suspending = false; wakeup_pending = false; /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; spin_unlock_irqrestore(&xmm_lock, flags); xmm_power_l2_resume(); spin_lock_irqsave(&xmm_lock, flags); } baseband_xmm_powerstate = status; break; default: baseband_xmm_powerstate = status; break; } spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("BB XMM POWER STATE = %d\n", status); }
void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = baseband_power_driver_data; int value = 0; unsigned long flags; pr_debug("%s\n", __func__); if (baseband_xmm_powerstate == status) return; switch (status) { case BBXMM_PS_L0: if (modem_sleep_flag) { pr_info("%s Resume from L3 without calling resume" "function\n", __func__); baseband_xmm_power_driver_handle_resume(data); } pr_info("L0\n"); value = gpio_get_value(data->modem.xmm.ipc_hsic_active); pr_debug("before L0 ipc_hsic_active=%d\n", value); if (!value) { pr_debug("before L0 gpio set ipc_hsic_active=1 ->\n"); gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); } if (modem_power_on) { modem_power_on = false; baseband_modem_power_on(data); } if (!wake_lock_active(&wakelock)) wake_lock(&wakelock); pr_debug("gpio host active high->\n"); break; case BBXMM_PS_L2: pr_info("L2\n"); wake_unlock(&wakelock); modem_sleep_flag = true; break; case BBXMM_PS_L3: if (baseband_xmm_powerstate == BBXMM_PS_L2TOL0) { if (!data->modem.xmm.ipc_ap_wake) { spin_lock_irqsave(&xmm_lock, flags); wakeup_pending = true; spin_unlock_irqrestore(&xmm_lock, flags); pr_info("%s: L2 race condition-CP wakeup" " pending\n", __func__); } } pr_info("L3\n"); if (wake_lock_active(&wakelock)) { pr_info("%s: releasing wakelock before L3\n", __func__); wake_unlock(&wakelock); } gpio_set_value(data->modem.xmm.ipc_hsic_active, 0); /* do this only from L2 state (going to suspend) */ if (baseband_xmm_powerstate == BBXMM_PS_L2) tegra_baseband_rail_off(); pr_debug("gpio host active low->\n"); break; case BBXMM_PS_L2TOL0: /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); baseband_xmm_power_L2_resume(); } break; case BBXMM_PS_L3TOL0: /* poweron rail for L3 -> L0 (system resume) */ pr_debug("BB XMM L3 -> L0, turning on power rail.\n"); tegra_baseband_rail_on(); break; default: break; } baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); }
static int xmm_power_on(struct platform_device *device) { struct baseband_power_platform_data *pdata = device->dev.platform_data; struct xmm_power_data *data = &xmm_power_drv_data; unsigned long flags; pr_debug("%s {\n", __func__); /* check for platform data */ if (!pdata) { pr_err("%s: !pdata\n", __func__); return -EINVAL; } if (baseband_xmm_get_power_status() != BBXMM_PS_UNINIT) return -EINVAL; /* 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); /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_INIT2; spin_unlock_irqrestore(&xmm_lock, flags); /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", __func__); modem_power_on = true; if (pdata->hsic_register) data->hsic_device = pdata->hsic_register (pdata->ehci_device); else pr_err("%s: hsic_register is missing\n", __func__); register_hsic_device = false; baseband_modem_power_on(pdata); } else { /* register usb host controller */ if (pdata->hsic_register) data->hsic_device = pdata->hsic_register (pdata->ehci_device); /* turn on modem */ pr_debug("%s call baseband_modem_power_on_async\n", __func__); baseband_modem_power_on_async(pdata); } } else { /* reset flashed modem then it will respond with * ap-wake rising followed by falling gpio */ pr_debug("%s: reset flash modem\n", __func__); modem_power_on = false; spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; spin_unlock_irqrestore(&xmm_lock, flags); gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); forced_abort_hubevent = 0; xmm_power_reset_on(pdata); } pr_debug("%s }\n", __func__); return 0; }
static int baseband_xmm_power_on(struct platform_device *device) { struct baseband_power_platform_data *data = (struct baseband_power_platform_data *) device->dev.platform_data; int ret; pr_debug("%s {\n", __func__); /* check for platform data */ if (!data) { pr_err("%s: !data\n", __func__); return -EINVAL; } if (baseband_xmm_powerstate != BBXMM_PS_UNINIT) return -EINVAL; tegra_baseband_rail_on(); /* reset the state machine */ baseband_xmm_powerstate = BBXMM_PS_INIT; modem_sleep_flag = false; if (modem_ver < XMM_MODEM_VER_1130) ipc_ap_wake_state = IPC_AP_WAKE_INIT1; else ipc_ap_wake_state = IPC_AP_WAKE_INIT2; pr_debug("%s wake_st(%d) modem version %d\n", __func__, ipc_ap_wake_state, modem_ver); /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", __func__); modem_power_on = true; if (data->hsic_register) data->modem.xmm.hsic_device = data->hsic_register(); else pr_err("%s: hsic_register is missing\n", __func__); register_hsic_device = false; } else { /* register usb host controller */ if (data->hsic_register) data->modem.xmm.hsic_device = data->hsic_register(); /* turn on modem */ pr_debug("%s call baseband_modem_power_on\n", __func__); baseband_modem_power_on(data); } } ret = enable_irq_wake(gpio_to_irq(data->modem.xmm.ipc_ap_wake)); if (ret < 0) pr_err("%s: enable_irq_wake error\n", __func__); pr_debug("%s }\n", __func__); return 0; }
void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = baseband_power_driver_data; int value = 0; unsigned long flags; pr_debug("%s\n", __func__); if (baseband_xmm_powerstate == status) return; switch (status) { case BBXMM_PS_L0: /*if (modem_sleep_flag) { pr_info("%s Resume from L3 without calling resume" "function\n", __func__); baseband_xmm_power_driver_handle_resume(data); }*/ pr_info("L0\n"); value = gpio_get_value(data->modem.xmm.ipc_hsic_active); pr_debug("before L0 ipc_hsic_active=%d\n", value); if (!value) { pr_debug("before L0 gpio set ipc_hsic_active=1 ->\n"); gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); } if (modem_power_on) { modem_power_on = false; baseband_modem_power_on(data); } if (!wake_lock_active(&wakelock)) wake_lock(&wakelock); pr_debug("gpio host active high->\n"); break; case BBXMM_PS_L2: pr_info("L2\n"); wake_unlock(&wakelock); modem_sleep_flag = true; break; case BBXMM_PS_L3: if (baseband_xmm_powerstate == BBXMM_PS_L2TOL0) { if (!gpio_get_value(data->modem.xmm.ipc_ap_wake)) { spin_lock_irqsave(&xmm_lock, flags); wakeup_pending = true; spin_unlock_irqrestore(&xmm_lock, flags); pr_info("%s: L2 race condition-CP wakeup" " pending\n", __func__); } } pr_info("L3\n"); if (wake_lock_active(&wakelock)) { pr_info("%s: releasing wakelock before L3\n", __func__); wake_unlock(&wakelock); } if (register_hsic_device != true && wakeup_pending == false) { gpio_set_value(data->modem.xmm.ipc_hsic_active, 0); pr_debug("gpio host active low->\n"); } break; case BBXMM_PS_L2TOL0: /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); baseband_xmm_power_L2_resume(); } else goto exit_without_state_change; default: break; } baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); return; exit_without_state_change: pr_info("BB XMM POWER STATE = %d (not change to %d)\n", baseband_xmm_powerstate, status); return; }
void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = baseband_power_driver_data; int value = 0; unsigned long flags; pr_debug("%s n(%d),o(%d)\n", __func__, status, baseband_xmm_powerstate ); if (baseband_xmm_powerstate == status) return; switch (status) { case BBXMM_PS_L0: if (modem_sleep_flag) { pr_debug("%s Resume from L3 without calling resume" "function\n", __func__); baseband_xmm_power_driver_handle_resume(data); } pr_debug("PM_ST : L0\n"); baseband_xmm_powerstate = status; if (!wake_lock_active(&wakelock)) wake_lock(&wakelock); value = gpio_get_value(data->modem.xmm.ipc_hsic_active); //pr_debug("GPIO [R]: before L0 Host_active = %d \n", value); if (!value) { gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); pr_debug("GPIO [W]: L0 Host_active -> 1 \n"); } if (modem_power_on) { modem_power_on = false; baseband_modem_power_on(data); } pr_debug("gpio host active high->\n"); break; case BBXMM_PS_L2: pr_debug("PM_ST : L2\n"); baseband_xmm_powerstate = status; spin_lock_irqsave(&xmm_lock, flags); if (wakeup_pending) { spin_unlock_irqrestore(&xmm_lock, flags); baseband_xmm_power_L2_resume(); } else { spin_unlock_irqrestore(&xmm_lock, flags); if (wake_lock_active(&wakelock)) wake_unlock(&wakelock); modem_sleep_flag = true; } if (short_autosuspend && enable_short_autosuspend && &usbdev->dev) { pr_debug("autosuspend delay %d ms, disable short_autosuspend\n",DEFAULT_AUTOSUSPEND_DELAY); queue_work(workqueue_susp, &work_defaultsusp); short_autosuspend = false; } break; case BBXMM_PS_L3: if (baseband_xmm_powerstate == BBXMM_PS_L2TOL0) { if (!gpio_get_value(data->modem.xmm.ipc_ap_wake)) { spin_lock_irqsave(&xmm_lock, flags); wakeup_pending = true; spin_unlock_irqrestore(&xmm_lock, flags); pr_info("%s: L2 race condition-CP wakeup" " pending\n", __func__); } } pr_info("L3\n"); if (wake_lock_active(&wakelock)) { pr_debug("%s: releasing wakelock before L3\n", __func__); wake_unlock(&wakelock); } if (wakeup_pending == false) { gpio_set_value(data->modem.xmm.ipc_hsic_active, 0); pr_debug("gpio host active low->\n"); } break; case BBXMM_PS_L2TOL0: spin_lock_irqsave(&xmm_lock, flags); system_suspending = false; wakeup_pending = false; spin_unlock_irqrestore(&xmm_lock, flags); /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); baseband_xmm_power_L2_resume(); } baseband_xmm_powerstate = status; break; default: baseband_xmm_powerstate = status; break; } pr_debug("BB XMM POWER STATE = %s(%d)\n", pwrstate_cmt[status], status); }
static int baseband_xmm_power_on(struct platform_device *device) { struct baseband_power_platform_data *data = (struct baseband_power_platform_data *) device->dev.platform_data; int ret; pr_debug("%s {\n", __func__); /* check for platform data */ if (!data) { pr_err("%s: !data\n", __func__); return -EINVAL; } if (baseband_xmm_powerstate != BBXMM_PS_UNINIT) return -EINVAL; /* reset the state machine */ baseband_xmm_powerstate = BBXMM_PS_INIT; modem_sleep_flag = false; if (modem_ver < XMM_MODEM_VER_1130) ipc_ap_wake_state = IPC_AP_WAKE_INIT1; else ipc_ap_wake_state = IPC_AP_WAKE_INIT2; pr_debug("%s - %d\n", __func__, __LINE__); /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n",__func__); modem_power_on = true; if (data->hsic_register) data->modem.xmm.hsic_device = data->hsic_register(); else pr_err("%s: hsic_register is missing\n",__func__); register_hsic_device = false; } else { /* register usb host controller */ if (data->hsic_register) data->modem.xmm.hsic_device = data->hsic_register(); /* turn on modem */ pr_debug("%s call baseband_modem_power_on\n", __func__); baseband_modem_power_on(data); } } else { if (modem_ver >= XMM_MODEM_VER_1145) { pr_debug("%s: ver > 1145: IPC_AP_WAKE_IRQ_READY\n", __func__); ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; baseband_xmm_powerstate = BBXMM_PS_UNINIT; CP_initiated_L2toL0 = false; enum_repeat = ENUM_REPEAT_TRY_CNT; printk("##@%s forced_abort_hubevent <- 0\n", __func__); forced_abort_hubevent = 0; baseband_xmm_power_work->state = BBXMM_WORK_INIT; queue_work(workqueue,(struct work_struct *) baseband_xmm_power_work); } else pr_err("%s: Error, no support cp ver\n", __func__); } ret = enable_irq_wake(gpio_to_irq(data->modem.xmm.ipc_ap_wake)); if (ret < 0) pr_err("%s: enable_irq_wake error\n", __func__); pr_debug("%s }\n", __func__); return 0; }
void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value = 0; unsigned long flags; if (baseband_xmm_powerstate == status) return; pr_debug("%s\n", __func__); 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); */ } pr_info("L0\n"); baseband_xmm_powerstate = status; if (!wake_lock_active(&wakelock)) wake_lock_timeout(&wakelock, HZ*2); 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); } if (modem_power_on) { modem_power_on = false; baseband_modem_power_on(data); } break; case BBXMM_PS_L2: pr_info("L2\n"); baseband_xmm_powerstate = status; spin_lock_irqsave(&xmm_lock, flags); if (wakeup_pending) { spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("%s: wakeup pending\n", __func__); xmm_power_l2_resume(); } else { spin_unlock_irqrestore(&xmm_lock, flags); if (wake_lock_active(&wakelock)) wake_unlock(&wakelock); modem_sleep_flag = true; } break; case BBXMM_PS_L2TOL0: pr_debug("L2TOL0\n"); spin_lock_irqsave(&xmm_lock, flags); system_suspending = false; wakeup_pending = false; spin_unlock_irqrestore(&xmm_lock, flags); /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; pr_debug("BB XMM POWER STATE = %d\n", status); xmm_power_l2_resume(); } baseband_xmm_powerstate = status; break; default: baseband_xmm_powerstate = status; break; } pr_debug("BB XMM POWER STATE = %d\n", status); }