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);
}
示例#2
0
static inline void decide_pm_wake(struct modem_link_pm *pm,
				  enum pm_state c_state,
				  enum pm_state n_state)
{
	if (n_state == c_state)
		return;

	switch (n_state) {
	case PM_STATE_UNMOUNTED:
		unlock_pm_wake(pm);
		break;

	case PM_STATE_ACTIVE:
		lock_pm_wake(pm);
		break;

	default:
		break;
	}
}
示例#3
0
static inline void prepare_mount(struct modem_link_pm *pm)
{
	lock_pm_wake(pm);
	forbid_link_suspend(pm);
}