/**
@brief		finalize handling the PHONE_START command from CP

@param mld	the pointer to a mem_link_device instance
*/
static void finalize_cp_start(struct mem_link_device *mld)
{
	int ap_wakeup = gpio_get_value(mld->gpio_ap_wakeup);
	int cp_status = gpio_get_value(mld->gpio_cp_status);

	change_irq_type(mld->irq_ap_wakeup.num, ap_wakeup);
	change_irq_type(mld->irq_cp_status.num, cp_status);

	if (ap_wakeup) {
		if (wake_lock_active(&mld->ap_wlock))
			wake_lock(&mld->ap_wlock);
	} else {
		if (wake_lock_active(&mld->ap_wlock))
			wake_unlock(&mld->ap_wlock);
	}

	if (cp_status) {
		if (!wake_lock_active(&mld->ap_wlock))
			wake_lock(&mld->cp_wlock);
	} else {
		if (wake_lock_active(&mld->ap_wlock))
			wake_unlock(&mld->cp_wlock);
	}

	print_pm_status(mld);
}
static irqreturn_t cp_status_handler(int irq, void *data)
{
	struct mem_link_device *mld = (struct mem_link_device *)data;
	struct link_device *ld = &mld->link_dev;
	struct modem_ctl *mc = ld->mc;
	int cp_status = gpio_get_value(mld->gpio_cp_status);
	unsigned long flags;

	spin_lock_irqsave(&mld->pm_lock, flags);

	change_irq_type(irq, cp_status);

	if (!cp_online(mc))
		goto exit;

	if (cp_status) {
		if (!wake_lock_active(&mld->cp_wlock))
			wake_lock(&mld->cp_wlock);
	} else {
		gpio_set_value(mld->gpio_ap_status, 0);

		if (wake_lock_active(&mld->cp_wlock))
			wake_unlock(&mld->cp_wlock);
	}

exit:
	print_pm_status(mld);
	spin_unlock_irqrestore(&mld->pm_lock, flags);
	return IRQ_HANDLED;
}
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);
    }
}
/**
@brief	interrupt handler for a wakeup interrupt

1) Reads the interrupt value\n
2) Performs interrupt handling\n

@param irq	the IRQ number
@param data	the pointer to a data
*/
static irqreturn_t ap_wakeup_interrupt(int irq, void *data)
{
    struct mem_link_device *mld = (struct mem_link_device *)data;
    int ap_wakeup = gpio_get_value(mld->gpio_ap_wakeup);
    int cp_wakeup = gpio_get_value(mld->gpio_cp_wakeup);
    int cpu = raw_smp_processor_id();

    change_irq_type(irq, ap_wakeup);

    if (work_pending(&mld->cp_sleep_dwork.work))
        cancel_delayed_work(&mld->cp_sleep_dwork);

    if (ap_wakeup) {
        mld->last_cp2ap_intr = cpu_clock(cpu);
        if (!cp_wakeup)
            gpio_set_value(mld->gpio_cp_wakeup, 1);

        if (!wake_lock_active(&mld->ap_wlock))
            wake_lock(&mld->ap_wlock);

        if (mipi_lli_get_link_status() == LLI_UNMOUNTED)
            mipi_lli_set_link_status(LLI_WAITFORMOUNT);

        if (!mipi_lli_suspended())
            gpio_set_value(mld->gpio_ap_status, 1);

    } else {
        if (wake_lock_active(&mld->ap_wlock))
            wake_unlock(&mld->ap_wlock);

        if (mipi_lli_get_link_status() & LLI_WAITFORMOUNT)
            mipi_lli_set_link_status(LLI_UNMOUNTED);
        queue_delayed_work(system_nrt_wq, &mld->cp_sleep_dwork,
                           msecs_to_jiffies(sleep_timeout));
    }

    print_pm_status(mld);

    return IRQ_HANDLED;
}