static void stop_pm(struct mem_link_device *mld) { print_pm_status(mld); mif_disable_irq(&mld->irq_ap_wakeup); mif_disable_irq(&mld->irq_cp_status); }
static void stop_link_pm(struct modem_link_pm *pm) { unsigned long flags; enum pm_state state; enum pm_event event; spin_lock_irqsave(&pm->lock, flags); if (!pm->active) goto exit; pm->active = false; mif_disable_irq(&pm->cp2ap_wakeup_irq); mif_err("%s: PM %s_irq#%d handler disabled\n", pm->link_name, pm->cp2ap_wakeup_irq.name, pm->cp2ap_wakeup_irq.num); mif_disable_irq(&pm->cp2ap_status_irq); mif_err("%s: PM %s_irq#%d handler disabled\n", pm->link_name, pm->cp2ap_status_irq.name, pm->cp2ap_status_irq.num); state = pm->fsm.state; event = PM_EVENT_STOP_PM; set_pm_fsm(pm, state, PM_STATE_UNMOUNTED, event); print_pm_event(pm, event); exit: spin_unlock_irqrestore(&pm->lock, flags); }
static int ss300_off(struct modem_ctl *mc) { struct io_device *iod = mc->iod; struct link_device *ld = get_current_link(iod); unsigned long flags; int i; mif_disable_irq(&mc->irq_cp_active); mif_info("%s: %s: +++\n", mc->name, FUNC); print_mc_state(mc); spin_lock_irqsave(&mc->lock, flags); if (cp_offline(mc)) { spin_unlock_irqrestore(&mc->lock, flags); mif_err("%s: %s: OFFLINE already!!!\n", mc->name, FUNC); goto exit; } iod->modem_state_changed(iod, STATE_OFFLINE); spin_unlock_irqrestore(&mc->lock, flags); if (ld->close_tx) ld->close_tx(ld); #if 0 wait_for_link_unmount(mc, ld); #endif if (gpio_get_value(mc->gpio_cp_on) == 0) { mif_err("%s: cp_on == 0\n", mc->name); goto exit; } /* wait for cp_active for 3 seconds */ for (i = 0; i < 150; i++) { if (gpio_get_value(mc->gpio_phone_active)) break; msleep(20); } print_mc_state(mc); if (ld->off) ld->off(ld); if (gpio_get_value(mc->gpio_cp_reset)) { mif_err("%s: %s: cp_reset -> 0\n", mc->name, FUNC); gpio_set_value(mc->gpio_cp_reset, 0); print_mc_state(mc); } exit: mif_info("%s: %s: ---\n", mc->name, FUNC); return 0; }
static int ss300_on(struct modem_ctl *mc) { struct link_device *ld = get_current_link(mc->iod); int cp_on; int cp_reset; int cp_active; int cp_status; unsigned long flags; mif_err("+++\n"); spin_lock_irqsave(&ld->lock, flags); cp_on = gpio_get_value(mc->gpio_cp_on); cp_reset = gpio_get_value(mc->gpio_cp_reset); cp_active = gpio_get_value(mc->gpio_phone_active); cp_status = gpio_get_value(mc->gpio_cp_status); mif_err("state:%s cp_on:%d cp_reset:%d cp_active:%d cp_status:%d\n", mc_state(mc), cp_on, cp_reset, cp_active, cp_status); mc->phone_state = STATE_OFFLINE; gpio_set_value(mc->gpio_pda_active, 1); if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) { wake_lock(mc->wake_lock); mif_err("%s->wake_lock locked\n", mc->name); } if (ld->ready) ld->ready(ld); spin_unlock_irqrestore(&ld->lock, flags); mif_disable_irq(&mc->irq_cp_active); gpio_set_value(mc->gpio_cp_on, 0); msleep(100); gpio_set_value(mc->gpio_cp_reset, 0); msleep(500); gpio_set_value(mc->gpio_cp_on, 1); msleep(100); if (ld->reset) ld->reset(ld); gpio_set_value(mc->gpio_cp_reset, 1); msleep(300); mif_err("---\n"); return 0; }
static int ss300_on(struct modem_ctl *mc) { struct io_device *iod = mc->iod; struct link_device *ld = get_current_link(iod); unsigned long flags; mif_disable_irq(&mc->irq_cp_active); mif_info("%s: %s: +++\n", mc->name, FUNC); print_mc_state(mc); spin_lock_irqsave(&mc->lock, flags); iod->modem_state_changed(iod, STATE_OFFLINE); gpio_set_value(mc->gpio_pda_active, 1); if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) { wake_lock(mc->wake_lock); mif_err("%s->wake_lock locked\n", mc->name); } if (ld->ready) ld->ready(ld); spin_unlock_irqrestore(&mc->lock, flags); gpio_set_value(mc->gpio_cp_on, 0); msleep(100); gpio_set_value(mc->gpio_cp_reset, 0); print_mc_state(mc); msleep(500); gpio_set_value(mc->gpio_cp_on, 1); msleep(100); if (ld->reset) ld->reset(ld); if (mc->gpio_ap_dump_int) gpio_set_value(mc->gpio_ap_dump_int, 0); gpio_set_value(mc->gpio_cp_reset, 1); print_mc_state(mc); msleep(300); mif_info("%s: %s: ---\n", mc->name, FUNC); return 0; }
static int ss333_dump_reset(struct modem_ctl *mc) { struct io_device *iod = mc->iod; struct link_device *ld = get_current_link(iod); unsigned int gpio_cp_reset = mc->gpio_cp_reset; unsigned long flags; mif_disable_irq(&mc->irq_cp_active); mif_info("%s: %s: +++\n", mc->name, FUNC); print_mc_state(mc); spin_lock_irqsave(&mc->lock, flags); iod->modem_state_changed(iod, STATE_CRASH_EXIT); if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) { wake_lock(mc->wake_lock); mif_err("%s->wake_lock locked\n", mc->name); } if (ld->off) ld->off(ld); spin_unlock_irqrestore(&mc->lock, flags); gpio_set_value(gpio_cp_reset, 0); print_mc_state(mc); udelay(200); if (ld->reset) ld->reset(ld); gpio_set_value(gpio_cp_reset, 1); print_mc_state(mc); msleep(300); gpio_set_value(mc->gpio_ap_status, 1); mif_info("%s: %s: ---\n", mc->name, FUNC); return 0; }
static int ss300_dump_reset(struct modem_ctl *mc) { struct link_device *ld = get_current_link(mc->iod); unsigned int gpio_cp_reset = mc->gpio_cp_reset; unsigned long flags; spin_lock_irqsave(&ld->lock, flags); mif_err("+++\n"); if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) { wake_lock(mc->wake_lock); mif_err("%s->wake_lock locked\n", mc->name); } if (ld->ready) ld->ready(ld); spin_unlock_irqrestore(&ld->lock, flags); mif_disable_irq(&mc->irq_cp_active); gpio_set_value(gpio_cp_reset, 0); udelay(200); if (ld->reset) ld->reset(ld); gpio_set_value(gpio_cp_reset, 1); msleep(300); gpio_set_value(mc->gpio_ap_status, 1); mif_err("---\n"); return 0; }
static int init_pm(struct mem_link_device *mld) { int err; unsigned int gpio; unsigned int irq_ap_wakeup; unsigned int irq_cp_status; unsigned long flags; gpio_set_value(mld->gpio_ap_status, 0); /* Retrieve GPIO#, IRQ#, and IRQ flags for PM */ gpio = mld->gpio_ap_wakeup; irq_ap_wakeup = gpio_to_irq(gpio); mif_err("CP2AP_WAKEUP GPIO:%d IRQ:%d\n", gpio, irq_ap_wakeup); gpio = mld->gpio_cp_wakeup; mif_err("AP2CP_WAKEUP GPIO:%d\n", gpio); gpio = mld->gpio_cp_status; irq_cp_status = gpio_to_irq(gpio); mif_err("CP2AP_STATUS GPIO:%d IRQ:%d\n", gpio, irq_cp_status); gpio = mld->gpio_ap_status; mif_err("AP2CP_STATUS GPIO:%d\n", gpio); /* Initialize locks, completions, bottom halves, etc. */ wake_lock_init(&mld->ap_wlock, WAKE_LOCK_SUSPEND, "lli_ap_wlock"); wake_lock_init(&mld->cp_wlock, WAKE_LOCK_SUSPEND, "lli_cp_wlock"); INIT_DELAYED_WORK(&mld->cp_sleep_dwork, release_cp_wakeup); spin_lock_init(&mld->pm_lock); spin_lock_init(&mld->sig_lock); atomic_set(&mld->ref_cnt, 0); /* Enable IRQs for PM */ print_pm_status(mld); flags = (IRQF_TRIGGER_HIGH | IRQF_ONESHOT); mif_init_irq(&mld->irq_ap_wakeup, irq_ap_wakeup, "lli_cp2ap_wakeup", flags); err = mif_request_irq(&mld->irq_ap_wakeup, ap_wakeup_interrupt, mld); if (err) return err; mif_disable_irq(&mld->irq_ap_wakeup); mif_init_irq(&mld->irq_cp_status, irq_cp_status, "lli_cp2ap_status", flags); err = mif_request_irq(&mld->irq_cp_status, cp_status_handler, mld); if (err) return err; mif_disable_irq(&mld->irq_cp_status); return 0; }
int init_link_device_pm(struct link_device *ld, struct modem_link_pm *pm, struct link_pm_svc *pm_svc, void (*fail_fn)(struct modem_link_pm *), void (*cp_fail_fn)(struct modem_link_pm *)) { struct modem_data *mdata = ld->mdm_data; int err; int cp2ap_wakeup; int cp2ap_status; unsigned int num; unsigned long flags; char name[MAX_NAME_LEN]; /* Set up variables for PM */ pm->link_name = ld->name; pm->fail_handler = fail_fn; pm->cp_fail_handler = cp_fail_fn; /* Retrieve GPIO pins and IRQ numbers for PM */ pm->gpio_cp2ap_wakeup = mdata->gpio_ap_wakeup; pm->gpio_ap2cp_wakeup = mdata->gpio_cp_wakeup; pm->gpio_cp2ap_status = mdata->gpio_cp_status; pm->gpio_ap2cp_status = mdata->gpio_ap_status; num = gpio_to_irq(pm->gpio_cp2ap_wakeup); flags = IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_ONESHOT; snprintf(name, MAX_NAME_LEN, "%s_cp2ap_wakeup", pm->link_name); mif_init_irq(&pm->cp2ap_wakeup_irq, num, name, flags); num = gpio_to_irq(pm->gpio_cp2ap_status); flags = IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_ONESHOT; snprintf(name, MAX_NAME_LEN, "%s_cp2ap_status", pm->link_name); mif_init_irq(&pm->cp2ap_status_irq, num, name, flags); mif_err("CP2AP_WAKEUP GPIO:%d IRQ:%d\n", pm->gpio_cp2ap_wakeup, pm->cp2ap_wakeup_irq.num); mif_err("AP2CP_WAKEUP GPIO:%d\n", pm->gpio_ap2cp_wakeup); mif_err("CP2AP_STATUS GPIO:%d IRQ:%d\n", pm->gpio_cp2ap_status, pm->cp2ap_status_irq.num); mif_err("AP2CP_STATUS GPIO:%d\n", pm->gpio_ap2cp_status); /* Register cp2ap_wakeup IRQ handler */ cp2ap_wakeup = gpio_get_value(pm->gpio_cp2ap_wakeup); change_irq_level(pm->cp2ap_wakeup_irq.num, cp2ap_wakeup); err = mif_request_irq(&pm->cp2ap_wakeup_irq, cp2ap_wakeup_handler, pm); if (err) { mif_err("%s: ERR! request_irq(%s#%d) fail (%d)\n", pm->link_name, pm->cp2ap_wakeup_irq.name, pm->cp2ap_wakeup_irq.num, err); return err; } mif_disable_irq(&pm->cp2ap_wakeup_irq); mif_err("%s: %s_irq#%d handler registered\n", pm->link_name, pm->cp2ap_wakeup_irq.name, pm->cp2ap_wakeup_irq.num); /* Register cp2ap_status IRQ handler */ cp2ap_status = gpio_get_value(pm->gpio_cp2ap_status); change_irq_level(pm->cp2ap_status_irq.num, cp2ap_status); err = mif_request_irq(&pm->cp2ap_status_irq, cp2ap_status_handler, pm); if (err) { mif_err("%s: ERR! request_irq(%s#%d) fail (%d)\n", pm->link_name, pm->cp2ap_status_irq.name, pm->cp2ap_status_irq.num, err); free_irq(pm->cp2ap_wakeup_irq.num, pm); return err; } mif_disable_irq(&pm->cp2ap_status_irq); mif_err("%s: %s_irq#%d handler registered\n", pm->link_name, pm->cp2ap_status_irq.name, pm->cp2ap_status_irq.num); /* Initialize common variables for PM */ spin_lock_init(&pm->lock); snprintf(pm->wlock_name, MAX_NAME_LEN, "%s_pm_wlock", pm->link_name); wake_lock_init(&pm->wlock, WAKE_LOCK_SUSPEND, pm->wlock_name); snprintf(pm->wq_name, MAX_NAME_LEN, "%s_pm_wq", pm->link_name); flags = WQ_NON_REENTRANT | WQ_UNBOUND | WQ_HIGHPRI; pm->wq = alloc_workqueue(pm->wq_name, flags, 1); if (!pm->wq) { mif_err("%s: ERR! fail to create %s\n", pm->link_name, pm->wq_name); return -EFAULT; } INIT_DELAYED_WORK(&pm->cp_free_dwork, cp_free_work_func); init_pm_fsm(pm); /* Register PM functions set by the common link PM framework and used by each link device driver */ pm->start = start_link_pm; pm->stop = stop_link_pm; pm->request_hold = request_hold; pm->release_hold = release_hold; pm->link_active = link_active; return 0; }