static void start_link_pm(struct modem_link_pm *pm, enum pm_event event)
{
	int cp2ap_wakeup;
	int cp2ap_status;
	enum pm_state state;
	unsigned long flags;

	spin_lock_irqsave(&pm->lock, flags);

	if (pm->active) {
		mif_err("%s: PM is already ACTIVE\n", pm->link_name);
		goto exit;
	}

	lock_pm_wake(pm);

	if (event == PM_EVENT_LOCK_ON) {
		state = PM_STATE_LOCKED_ON;
		assert_ap2cp_wakeup(pm);
		assert_ap2cp_status(pm);
	} else if (event == PM_EVENT_CP_BOOTING) {
		state = PM_STATE_CP_BOOTING;
		assert_ap2cp_wakeup(pm);
		assert_ap2cp_status(pm);
	} else {
		state = PM_STATE_UNMOUNTED;
		release_ap2cp_wakeup(pm);
		release_ap2cp_status(pm);
	}

	/*
	Enable every CP-to-AP IRQ and set it as a wake-up source
	*/
	cp2ap_wakeup = gpio_get_value(pm->gpio_cp2ap_wakeup);
	change_irq_level(pm->cp2ap_wakeup_irq.num, cp2ap_wakeup);
	mif_enable_irq(&pm->cp2ap_wakeup_irq);

	cp2ap_status = gpio_get_value(pm->gpio_cp2ap_status);
	change_irq_level(pm->cp2ap_status_irq.num, cp2ap_status);
	mif_enable_irq(&pm->cp2ap_status_irq);

	set_pm_fsm(pm, PM_STATE_UNMOUNTED, state, event);

	pm->hold_requested = false;

	pm->active = true;

#ifdef DEBUG_MODEM_IF
	print_pm_fsm(pm);
#endif

exit:
	spin_unlock_irqrestore(&pm->lock, flags);
}
static int ss300_boot_off(struct modem_ctl *mc)
{
	unsigned long remain;
	unsigned long flags;
	mif_err("+++\n");

	remain = wait_for_completion_timeout(&mc->init_cmpl, MIF_INIT_TIMEOUT);
	if (remain == 0) {
		mif_err("T-I-M-E-O-U-T\n");
		mif_err("xxx\n");
		return -EAGAIN;
	}

	mif_enable_irq(&mc->irq_cp_active);

	spin_lock_irqsave(&mc->lock, flags);
	mc->bootd->modem_state_changed(mc->bootd, STATE_ONLINE);
	mc->iod->modem_state_changed(mc->iod, STATE_ONLINE);
	spin_unlock_irqrestore(&mc->lock, flags);

	atomic_set(&mc->forced_cp_crash, 0);

	mif_err("---\n");
	return 0;
}
static void start_pm(struct mem_link_device *mld)
{
    if (pm_enable) {
        int ap_wakeup = gpio_get_value(mld->gpio_ap_wakeup);
        int cp_status = gpio_get_value(mld->gpio_cp_status);

        print_pm_status(mld);

        change_irq_type(mld->irq_ap_wakeup.num, ap_wakeup);
        mif_enable_irq(&mld->irq_ap_wakeup);

        change_irq_type(mld->irq_cp_status.num, cp_status);
        mif_enable_irq(&mld->irq_cp_status);
    } else {
        wake_lock(&mld->ap_wlock);
    }
}
static int ss300_boot_done(struct modem_ctl *mc)
{
	mif_err("+++\n");

	if (mc->wake_lock && wake_lock_active(mc->wake_lock)) {
		wake_unlock(mc->wake_lock);
		mif_err("%s->wake_lock unlocked\n", mc->name);
	}

	mif_enable_irq(&mc->irq_cp_active);

	mif_err("---\n");
	return 0;
}